当前访客身份:游客 [ 登录 | 加入 OSCHINA ]

代码分享

当前位置:
代码分享 » C/C++  » 编程基础
codec-avs

C++ Primer Plus 第13章课后练习

codec-avs 发布于 2016年08月17日 14时, 0评/1329阅
分享到: 
收藏 +0
0
C++ Primer Plus 第13章课后练习
标签: <无>

代码片段(1) [全屏查看所有代码]

1. [文件] T_13.cpp ~ 13KB     下载(15)     跳至 [1] [全屏预览]

#include <cstring>
#include <iostream>
namespace cd_test
{
	class Cd
	{
	private:
		char * performers;
		char * label;
		int selections;
		double playtime;
	public:
		Cd(const char * s1, const char * s2, int n, double x);
		Cd(const Cd & d);
		Cd();
		virtual ~Cd(); // comment out virtual and i dont find any difference
		virtual void Report() const;
		virtual Cd & operator=(const Cd & d);
		// test rewriting function without virtual
		void hard_rewrite() const {std::cout << "[cd] solely for hard rewrite test\n";};
	};

	Cd::Cd(const char * s1, const char * s2, int n, double x)
	{
		int len = strlen(s1);
		performers = new char[len + 1];
		strcpy(performers, s1);
		len = strlen(s2);
		label = new char[len+1];
		strcpy(label, s2);
		selections = n;
		playtime = x;
	}

	Cd::Cd(const Cd & d)
	{	
		int len = strlen(d.performers);
		performers = new char[len+1];
		strcpy(performers, d.performers);
		len = strlen(d.label);
		label = new char[len+1];
		strcpy(label, d.label);
		selections = d.selections;
		playtime = d.playtime;		
	}

	Cd::Cd()
	{
		performers = new char[1];
		performers[1] = '\0';
		label = new char[1];
		label[1] = '\0';
		selections = 0;
		playtime = 0;
	}

	Cd::~Cd()
	{
		std::cout << "Destructing Cd" << std::endl;
		delete [] performers;
		delete [] label;
	}

	void Cd::Report() const
	{
		std::cout << "-------------->Reporting Cd: \n"
					<< "               performers: " << performers << std::endl
					<< "                    label: " << label << std::endl
					<< "               selections: " << selections << std::endl
					<< "                 playtime: " << playtime << std::endl;
	}

	Cd & Cd::operator=(const Cd & d)
	{
		if (this == &d)
			return *this;

		int len = strlen(d.performers);
		performers = new char[len+1];
		strcpy(performers, d.performers);
		len = strlen(d.label);
		label = new char[len+1];
		strcpy(label, d.label);
		selections = d.selections;
		playtime = d.playtime;		
		return *this;
	}

	class Classic : public Cd
	{
	private:
		char * major;
	public:
		Classic(const char * s1, const char * s2, int n, double x, const char * m);
		Classic(const Classic & c);
		Classic();
		virtual ~Classic();
		virtual void Report() const;
		virtual Classic & operator=(const Classic & c);		
		void hard_rewrite() const {std::cout << "[classic] see what happens?\n";};
	};

	Classic::Classic(const char * s1, const char * s2, int n, double x, const char * m):Cd(s1, s2, n, x)
	{
		int len = strlen(m);
		major = new char[len+1];
		strcpy(major, m);
	}

	Classic::Classic(const Classic & c):Cd(c)
	{
		int len = strlen(c.major);
		major = new char[len+1];		
		strcpy(major, c.major);
	}

	Classic::Classic():Cd()
	{
		major = new char[1];
		major[1] = '\0';		
	}

	Classic::~Classic()
	{
		std::cout << "Destructing Classic" << std::endl;
		delete [] major;
	}

	void Classic::Report() const
	{
		std::cout << "-------------->Reporting Classic: \n"
					<< "                         major: " << major << std::endl;
		Cd::Report();
	}

	Classic & Classic::operator=(const Classic & c)
	{
		if(this == &c)
			return *this;
		Cd::operator=(c);
		int len = strlen(c.major);
		delete [] major;
		major = new char[len+1];
		strcpy(major, c.major);

		return *this;
	}
}


namespace dma_abc
{
	class ABC
	{
	private:
		char * label;
		int rating;
	public:
		ABC(const char * l = "null", int r = 0);
		// 对于有动态内存分配的类,必须要考虑的方法
		ABC(const ABC & rs);
		virtual ~ABC() = 0;
		ABC & operator=(const ABC & rs);
		virtual void View() const;
		friend std::ostream & operator<<(std::ostream & os, const ABC & rs);
	};

	class baseDMA : public ABC
	{
	private:
	public:
		baseDMA(const char * l = "null", int r = 0);
	};

	class lackDMA : public ABC
	{
	private:
		char color[40];
	public:
		lackDMA(const char * l = "null", int r = 0, const char * c = "blank");
		lackDMA(const ABC & rs, const char * c = "blank");
		// derived class without dynamic memory allocation
		// default constructor 
		// uses implicit copy constructor
		// uses implicit assignment operator
		virtual void View() const;
	};

	class hasDMA : public ABC
	{
	private:
		char * style;
	public:
		// the 3 methods
		virtual ~hasDMA();
		hasDMA(const hasDMA &);
		hasDMA & operator=(const hasDMA &);
		// baisc constructor
		hasDMA(const char * l = "null", int r = 0, const char * s = "chinese style");
		hasDMA(const char *, const hasDMA &);
		virtual void View() const;
	};

	ABC::ABC(const char * l, int r)
	{
		// memory allocation needed before copy operation
		label = new char[strlen(l) + 1];
		strcpy(label, l);
		rating = r;
	}

	ABC::ABC(const ABC & rs)
	{
		label = new char[strlen(rs.label) + 1];
		strcpy(label, rs.label);
		rating = rs.rating;
	}

	ABC::~ABC()
	{
		delete [] label;
	}

	ABC & ABC::operator=(const ABC & rs)
	{
		if (this == &rs)
			return *this;
		delete [] label;
		label = new char[strlen(rs.label) + 1];
		strcpy(label, rs.label);
		rating = rs.rating;
		return *this;
	}

	void ABC::View() const
	{
		std::cout << "Label: " << label << std::endl;
		std::cout << "Rating: " << rating << std::endl;
	}

	std::ostream & operator<<(std::ostream & os, const ABC & rs)
	{
		rs.View();
		return os;
	}

	baseDMA::baseDMA(const char * l, int r):ABC(l, r) // P484 ref
	{
	}

	lackDMA::lackDMA(const char * l, int r, const char * c):ABC(l,r)
	{
		// char color[40] already allocates memory
		strncpy(color, c, 39);
		color[39] = '\0';
	}

	lackDMA::lackDMA(const ABC & rs, const char * c):ABC(rs)
	{
		strncpy(color, c, 39);
		color[39] = '\0';		
	}
	void lackDMA::View() const
	{
		ABC::View();
		std::cout << "Color: " << color << std::endl;
	}

	hasDMA::~hasDMA()
	{
		delete [] style;
	}

	hasDMA::hasDMA(const hasDMA & rs):ABC(rs)
	{	
		delete [] style;
		style = new char[strlen(rs.style) + 1];
		strcpy(style, rs.style);
	}

	hasDMA & hasDMA::operator=(const hasDMA & rs)
	{
		if (this == &rs)
			return *this;
		ABC::operator=(rs);
		delete [] style;
		style = new char[strlen(rs.style) + 1];
		strcpy(style, rs.style);		
		return *this;
	}

	hasDMA::hasDMA(const char * l, int r, const char * s):ABC(l,r)
	{
		style = new char[strlen(s) + 1];
		strcpy(style, s);
	}

	hasDMA::hasDMA(const char * s, const hasDMA & rs):ABC(rs)
	{
		style = new char[strlen(s) + 1];
		strcpy(style, s);		
	}

	void hasDMA::View() const
	{
		ABC::View();
		std::cout << "Style: " << style << std::endl;
	}

}

namespace bottlespace
{
	class Port
	{
	private:
		char * brand;
		char style[20];
		int bottles;
	public:
		Port(const char * br = "none", const char * st = "none", int b = 0);
		Port(const Port &);
		virtual ~Port(){delete [] brand;};
		virtual Port & operator=(const Port &);
		Port & operator+=(int);
		Port & operator-=(int);
		int BottleCount() const {return bottles;};
		virtual void Show() const;
		friend std::ostream & operator<<(std::ostream &, const Port &);
	};


	class VintagePort : public Port
	{
	private:
		char * nickname;
		int year;
	public:
		VintagePort(); // no default value for the following init, so a empty constructor needed in case user want
		VintagePort(const char * br, const char * st, int b, const char * nm, int y);
		VintagePort(const VintagePort & vp);
		~VintagePort(){delete [] nickname;};
		// the following 2 methods redefined for comparision with nickname and year while showing the 2 elements
		VintagePort & operator=(const VintagePort & vp); // this is not rewriting virtual operator=(const Port &);
		virtual VintagePort & operator=(const Port &); // this is the correct version of rewriting virtual operator= in Port class, will cause dynamic binding
		void Show() const; // operator+-= and BottleCount not redefined for non new added elements involved
		friend std::ostream & operator<<(std::ostream & os, const VintagePort & vp);
	};

	Port::Port(const char * br, const char * st, int b)
	{
		brand = new char[strlen(br) + 1];
		strcpy(brand, br);
		strncpy(style, st, 19);
		style[19] = '\0';
		bottles = b;
	}

	Port::Port(const Port & p)
	{
		brand = new char[strlen(p.brand) + 1];
		strcpy(brand, p.brand);
		strncpy(style, p.style, 19);
		style[19] = '\0';
		bottles = p.bottles;		
	}

	Port & Port::operator=(const Port & p)
	{
		std::cout << "in Port & Port::operator=(const Port & p) " << std::endl;
		if(this == &p)
			return *this;
		delete [] brand;
		brand = new char[strlen(p.brand) + 1];
		strcpy(brand, p.brand);
		strncpy(style, p.style, 19);
		style[19] = '\0';
		bottles = p.bottles;		
		return *this;
	}

	Port & Port::operator+=(int b)
	{
		bottles += b;
		return *this;
	}

	Port & Port::operator-=(int b)
	{
		bottles -= b;
		return *this;
	}

	void Port::Show() const
	{
		std::cout << "Brand: " << brand << std::endl;
		std::cout << "Style: " << style << std::endl;
		std::cout << "Bottles: " << bottles << std::endl;
	}

	std::ostream & operator<<(std::ostream & os, const Port & p)
	{
		p.Show();
		return os;
	}

	VintagePort::VintagePort():Port()
	{
		nickname = new char[1];
		nickname[0] = '\0';
		year = 1999;
	}

	VintagePort::VintagePort(const char * br, const char * st, int b, const char * nm, int y) : Port(br, st, b) // ? br, b
	{
		nickname = new char[strlen(nm) + 1];
		strcpy(nickname, nm);
		year = y;
	}


	VintagePort::VintagePort(const VintagePort & vp) : Port(vp)
	{
		nickname = new char[strlen(vp.nickname) + 1];
		strcpy(nickname, vp.nickname);
		year = vp.year;
	}

	VintagePort & VintagePort::operator=(const VintagePort & vp)
	{
		std::cout << "in VintagePort & VintagePort::operator=(const VintagePort & vp)" << std::endl;
		if(this == &vp)
			return *this;
		Port::operator=(vp);
		delete [] nickname;
		nickname = new char[strlen(vp.nickname) + 1];
		strcpy(nickname, vp.nickname);
		year = vp.year;

		return *this;
	}

	VintagePort & VintagePort::operator=(const Port & p)
	{
		std::cout << "in VintagePort & VintagePort::operator=(const Port & p)" << std::endl;
		if(this == &p)
			return *this;
		Port::operator=(p);
		return *this;
	}

	void VintagePort::Show() const
	{
		Port::Show();
		std::cout << "Nickname: " << nickname << std::endl;
		std::cout << "Year: " << year << std::endl;
	}

	std::ostream & operator<<(std::ostream & os, const VintagePort & vp)
	{
		vp.Show();
		return os;
	}

}



void test_classic();
void Bravo(const cd_test::Cd & disk);
void test_dma();
void test_port();
int main()
{
	// test_classic();
	// test_dma();
	test_port();
	// int i = 0;
	// do
	// {
	// 	std::cout << "i = " << i << std::endl;

	// 	if(i==1000)
	// 		break;
	// 	else
	// 		std::cout << "somepost i functions" << std::endl;

	// 	i++;

	// }while(1);

	// std::cout << "out of do while loop" << std::endl;

	return 0;
}

void test_classic()
{
	using namespace cd_test;
	Cd c1("Beatles", "Capitol", 14, 35.5);
	Classic c2 = Classic("Piano Sonata", "Alfred", 2, 57.17, "Philips");
	Cd *pcd = &c1;

	std::cout << "Using object directly:\n";
	c1.Report();
	c2.Report();
	c1.hard_rewrite();
	c2.hard_rewrite();

	std::cout << "Using type cd * pointer to objects:\n";
	pcd->Report();
	pcd->hard_rewrite();
	pcd = &c2;
	pcd->Report();
	pcd->hard_rewrite(); // so rewrite is rewrite, the only difference is with virtual or not? multipolymorphism 多态
	// and keep in mind this not overload 重载

	std::cout << "Calling a function with a Cd reference argument:\n";
	Bravo(c1);
	Bravo(c2);

	std::cout << "Testing assignment: ";
	Classic copy;
	copy = c2;
	copy.Report();


}

void Bravo(const cd_test::Cd & disk)
{
	disk.Report();
}

void test_dma()
{
	using std::cout;
	using std::endl;
	using namespace dma_abc;
	baseDMA shirt("Portabelly", 8);
	lackDMA balloon("red", 4, "Blimpo");
	hasDMA map("Mercator", 5, "Buffalo Keys");
	cout << shirt << endl;
	cout << balloon << endl;
	cout << map << endl;	
	lackDMA balloon2(balloon);
	hasDMA map2;
	map2 = map;
	ABC * pts[3];
	pts[0] = &shirt;
	pts[1] = &balloon;
	pts[2] = &map;
	for (int i = 0; i < 3; i++)
		cout << *pts[i] << endl;
	for (int i = 0; i < 3; i++)
		pts[i]->View();
}

void test_port()
{
	using std::cout;
	using std::endl;
	using namespace bottlespace;

	Port pt1("England", "ruby", 20);
	Port pt2;
	VintagePort vpt1("Scotland", "rails", 10, "scottish", 1890);
	cout << pt1 << endl;
	cout << pt2 << endl;
	pt1 += 200;
	pt2 += 10;
	cout << pt1 << endl;
	cout << pt2 << endl;
	vpt1 -= 999;
	cout << vpt1 << endl;
	pt2 = pt1;
	cout << pt2 << endl;
	cout << pt1.BottleCount() << endl;
	cout << vpt1.BottleCount() << endl;

	Port * pts[2];
	pts[0] = &pt1;
	pts[1] = &vpt1;

	for(int i = 0; i < 2; i++)
	{
		cout << *pts[i] << endl;
		pts[i]->Show();
	}

	Port cpt1("copyEngland", "ruby", 20);
	// for(int i = 0; i < 2; i++)
	// {
	// 	*pts[i] = cpt1;
	// }
	// cout << "-----copy test------" << endl;
	// cout << *pts[0] << endl;
	// cout << *pts[1] << endl;

	VintagePort cvpt1("copyScotland", "rails", 10, "copyscottish", 1891);
	for(int i = 0; i < 2; i++)
	{
		// once operator= made virtual, only operator= with signitures of operator=(const Port & p) will be called 
		// once remove virtual, only base version will be called 
		// and since with signiture of operator=(const Port & p) nickname and year of vintageport will not be assigned
		// in conslusion signiture directs the operation you can do in a rewritten virtual function
		*pts[i] = cvpt1;
	}
	cout << "-----copy test------" << endl;
	cout << *pts[0] << endl;
	cout << *pts[1] << endl; // 


	// vpt1 = pt1;	
	// vpt1 = cvpt1;
	// Port & test = vpt1;
	// test = cvpt1;	
}


开源中国-程序员在线工具:Git代码托管 API文档大全(120+) JS在线编辑演示 二维码 更多»

开源从代码分享开始 分享代码
codec-avs的其它代码 全部(9)...