(一四五)第十三章编程练习

1.以下面的类声明为基础:

// base class

class Cd { //represents a CD disk

private:

char performers[50];

char label[20];

int selections; //number of selections

double playtime; //playing time in minute

public:

Cd(char * s1, char * s2, int n, double x);

Cd(const Cd & d);

Cd();

~Cd();

void Report() const; //reports all CD data

Cd & operator=(const Cd & d);

};

派生出一个Classic类,并添加一组char成员,用于存储指出CD中主要作品的字符串。修改上述声明,使基类的搜有函数都是虚的。如果上述定义声明的某个方法并不需要,则请删除它。使用下面的程序测试您的产品:

#include<iostream>

using namespace std;

#include"classic.h" //which will contain #include cd.h

void Bravo( const Cd& disk);

int main()

{
Cd c1("beatles", "Capitol", 14, 35.5);

Classic c2 = Classic ("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17);

Cd *pcd=&c1;

 

cout<<"Using object directly:\n";

c1.Report(); //use Cd method

c2.Report(); //use Classic method

 

cout<<"Using type cd *pointer to objects:\n";

pcd->Report(); //use Cd method for cd object

pcd = &c2;

pcd->Report(); //use Classic method for classic object

 

cout<<"Calling a function with a Cd reference argument:\n";

Bravo(c1);

Bravo(c2);

 

cout<<"Testing assignment: ";

Classic copy;

copy = c2;

copy.Report();

 

return 0;

}

 

void Bravo(const Cd& disk)

{
disk.Report();

}

 

答:

//classic.h
class Cd {	//represents a CD disk
private:
	char performers[50];	//表演者
	char label[20];		//标签
	int selections;		//选择次数
	double playtime;	//播放时间
public:
	Cd(char * s1, char * s2, int n, double x);	//构造函数
	Cd() {  }
	virtual ~Cd() {}	//析构函数
	virtual void Report() const;	//报告所有数据
	virtual Cd & operator=(const Cd & d);	//赋值运算符
};

//派生出一个Classic类,并添加一组char成员,用于存储指出CD中主要作品的字符串。
//修改上述声明,使基类的搜有函数都是虚的。
//如果上述定义声明的某个方法并不需要,则请删除它。

class Classic :public Cd	//派生类
{
private:
	char productions[50];	//主要作品
public:
	Classic() {}
	Classic(const char*pr, char*s1, char *s2, int n, double x);	//构造函数
	virtual void Report()const;
	virtual Classic & operator=(const Classic & d);	//赋值运算符
};
//classic.cpp
#include<iostream>
#include"classic.h"
using std::cout;
using std::endl;

//Cd类
Cd::Cd(char * s1, char * s2, int n, double x)	//构造函数
{
	strcpy_s(performers, strlen(s1) + 1, s1);
	strcpy_s(label, strlen(s2) + 1, s2);
	selections = n;
	playtime = x;
}
void Cd::Report() const	//报告所有数据
{
	cout << "表演者:" << performers << endl;
	cout << "标  签:" << label << endl;
	cout << "选  择:" << selections << endl;
	cout << "总时长:" << playtime << "分钟" << endl;
}
Cd & Cd::operator=(const Cd & d)	//赋值运算符
{
	if (this == &d)return *this;
	strcpy_s(performers, strlen(d.performers) + 1, d.performers);
	strcpy_s(label, strlen(d.label) + 1, d.label);
	selections = d.selections;
	playtime = d.playtime;
	return *this;
}

//Classic类
Classic::Classic(const char*pr, char*s1, char *s2, int n, double x) :Cd(s1, s2, n, x)	//构造函数
{
	strcpy_s(productions, strlen(pr) + 1, pr);
}
void Classic::Report()const
{
	Cd::Report();
	cout << "主要作品:" << productions << endl;
}
Classic & Classic::operator=(const Classic & d)	//赋值运算符
{
	if (this == &d)return *this;
	Cd::operator=(d);
	strcpy_s(productions, strlen(d.productions) + 1, d.productions);
	return *this;
}

//1.cpp main函数测试用
#include<iostream>
using namespace std;
#include"classic.h"	//which will contain #include cd.h
void Bravo(const Cd& disk);
int main()
{
	Cd c1("beatles", "Capitol", 14, 35.5);
	Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17);
	Cd *pcd = &c1;

	cout << "Using object directly:\n";
	c1.Report();		//use Cd method
	c2.Report();		//use Classic method

	cout << "Using type cd *pointer to objects:\n";
	pcd->Report();	//use Cd method for cd object
	pcd = &c2;
	pcd->Report();	//use Classic method for classic object

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

	cout << "Testing assignment: ";
	Classic copy;
	copy = c2;
	copy.Report();
	system("pause");
	return 0;
}

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




 

 

 

 

 

 

 

 

 

 

 

2.完成练习1,但让两个类使用动态内存分配而不是长度固定的数组来记录字符串。

答:修改如下(只包含头文件和classic.cpp源代码文件)

//classic.h
class Cd {	//represents a CD disk
private:
	char *performers;	//表演者
	char *label;		//标签
	int selections;		//选择次数
	double playtime;	//播放时间
public:
	Cd(char * s1, char * s2, int n, double x);	//构造函数
	Cd() { delete[]performers;delete[]label; }
	virtual ~Cd() {}	//析构函数
	virtual void Report() const;	//报告所有数据
	virtual Cd & operator=(const Cd & d);	//赋值运算符
};

//派生出一个Classic类,并添加一组char成员,用于存储指出CD中主要作品的字符串。
//修改上述声明,使基类的搜有函数都是虚的。
//如果上述定义声明的某个方法并不需要,则请删除它。

class Classic :public Cd	//派生类
{
private:
	char *productions;	//主要作品
public:
	Classic() { delete[]productions; }
	Classic(const char*pr, char*s1, char *s2, int n, double x);	//构造函数
	virtual void Report()const;
	virtual Classic & operator=(const Classic & d);	//赋值运算符
};
//classic.cpp
#include<iostream>
#include"classic.h"
using std::cout;
using std::endl;

//Cd类
Cd::Cd(char * s1, char * s2, int n, double x)	//构造函数
{
	performers = new char[strlen(s1) + 1];
	strcpy_s(performers, strlen(s1) + 1, s1);
	label = new char[strlen(s1) + 1];
	strcpy_s(label, strlen(s2) + 1, s2);
	selections = n;
	playtime = x;
}
void Cd::Report() const	//报告所有数据
{
	cout << "表演者:" << performers << endl;
	cout << "标  签:" << label << endl;
	cout << "选  择:" << selections << endl;
	cout << "总时长:" << playtime << "分钟" << endl;
}
Cd & Cd::operator=(const Cd & d)	//赋值运算符
{
	if (this == &d)return *this;
	delete[]performers;
	performers = new char[strlen(d.performers) + 1];
	strcpy_s(performers, strlen(d.performers) + 1, d.performers);
	delete[]label;
	label = new char[strlen(d.label) + 1];
	strcpy_s(label, strlen(d.label) + 1, d.label);
	selections = d.selections;
	playtime = d.playtime;
	return *this;
}

//Classic类
Classic::Classic(const char*pr, char*s1, char *s2, int n, double x) :Cd(s1, s2, n, x)	//构造函数
{
	productions = new char[strlen(pr) + 1];
	strcpy_s(productions, strlen(pr) + 1, pr);
}
void Classic::Report()const
{
	Cd::Report();
	cout << "主要作品:" << productions << endl;
}
Classic & Classic::operator=(const Classic & d)	//赋值运算符
{
	if (this == &d)return *this;
	Cd::operator=(d);
	delete[]productions;
	productions = new char[strlen(d.productions) + 1];
	strcpy_s(productions, strlen(d.productions) + 1, d.productions);
	return *this;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.修改baseDMA-lacksDMA-hasDMA类层次,让三个类都从一个ABC派生而来,然后使用与程序清单13.10相似的程序对结果进行测试。也就是说,它应使用ABC指针数组,并让用户决定要创建的对象类型。在类定义中添加virtual View()方法以处理数据显示。

//DMA.h
//ABC
class DMA
{
private:
	char *label;
	int rating;
public:
	DMA(const char*l = "null", int r = 0);
	DMA(const DMA& dm);
	virtual ~DMA() { delete[]label; }
	virtual void view() = 0;
	DMA & operator=(const DMA&dm);
};

class baseDMA :public DMA
{
public:
	baseDMA(const char*l = "null", int r = 0) :DMA(l, r) {};
	~baseDMA() {};
	virtual void view();
};

class lackDMA :public DMA
{
private:
	char color[40];
public:
	lackDMA(const char*l = "null", int r = 0, char* m = "yellow") :DMA(l, r)
	{
		strcpy_s(color, strlen(m) + 1, m);
	}
	~lackDMA() {}
	virtual void view();
};

class hasDMA:public DMA
{
private:
	char * style;
public:
	hasDMA(const char*l = "null", int r = 0, const char*m="null");
	hasDMA(const DMA&dm, const char*m);
	hasDMA(const hasDMA& ha);
	virtual const hasDMA& operator=(const hasDMA& ha);
	~hasDMA() { delete[] style; }
	virtual void view();
};
//DMA.cpp
#include<iostream>
#include"DMA.h"
using std::cout;
using std::endl;
//ABC
DMA::DMA(const char*l, int r)
{
	label = new char[strlen(l) + 1];
	strcpy_s(label, strlen(l) + 1, l);
	rating = r;
}
DMA::DMA(const DMA& dm)
{
	label = new char[strlen(dm.label) + 1];
	strcpy_s(label, strlen(dm.label) + 1, dm.label);
	rating = dm.rating;
}
DMA & DMA::operator=(const DMA&dm)
{
	if (this == &dm)return *this;
	delete[]label;
	label = new char[strlen(dm.label) + 1];
	strcpy_s(label, strlen(dm.label) + 1, dm.label);
	rating = dm.rating;
	return *this;
}
void DMA::view()
{
	cout << "**********" << endl;
	cout << "label:" << label << endl;
}

//baseDMA
void baseDMA::view()
{
	DMA::view();
}

//lackDMA
void lackDMA::view()
{
	DMA::view();
	cout << "color:" << color << endl;
}

//hasDMA
hasDMA::hasDMA(const char*l, int r, const char*m) :DMA(l, r)
{
	style = new char[strlen(m) + 1];
	strcpy_s(style, strlen(m) + 1, m);
}
hasDMA::hasDMA(const DMA&dm, const char*m) :DMA(dm)
{
	style = new char[strlen(m) + 1];
	strcpy_s(style, strlen(m) + 1, m);
}
hasDMA::hasDMA(const hasDMA& ha) :DMA(ha)
{
	style = new char[strlen(ha.style) + 1];
	strcpy_s(style, strlen(ha.style) + 1, ha.style);
}
const hasDMA& hasDMA::operator=(const hasDMA& ha)
{
	if (this == &ha)return *this;
	DMA::operator=(ha);
	delete[]style;
	style = new char[strlen(ha.style) + 1];
	strcpy_s(style, strlen(ha.style) + 1, ha.style);
	return *this;
}
void hasDMA::view()
{
	DMA::view();
	cout << "style:" << style << endl;
}
//1.cpp main函数测试用
#include<iostream>
#include"DMA.h"
using namespace std;

int main()
{
	DMA* one[3];	//ABC类指针
	for (int i = 0;i < 3;i++)
	{
		cout << "请输入你的选择:\n1.使用baseDMA类\t2.使用lackDMA类\t3.使用hasDMA类" << endl;
		cout << "选择->";
		int choice;
		cin >> choice;
		cin.sync();
		cin.clear();
		char *label = new char[30];
		cout << "请输入标签:";
		cin >> label;
		cout << "请输入等级:";
		int rating;
		cin >> rating;

		char *color = new char[30];
		char *style = new char[30];
		if (choice == 2)
		{
			cout << "请输入颜色:";
			cin >> color;
		}
		else if (choice == 3)
		{
			cout << "请输入风格:";
			cin >> style;
		}

		if (choice == 1)
			one[i] = new baseDMA(label, rating);
		else if (choice == 2)
			one[i] = new lackDMA(label, rating, color);
		else if (choice == 3)
			one[i] = new hasDMA(label, rating, style);
	}	//输入for结束
	for (int i = 0;i < 3;i++)	//显示
		one[i]->view();
	system("pause");
	return 0;
}

显示:

请输入你的选择:
1.使用baseDMA类 2.使用lackDMA类 3.使用hasDMA类
选择->1
请输入标签:A
请输入等级:10
请输入你的选择:
1.使用baseDMA类 2.使用lackDMA类 3.使用hasDMA类
选择->2
请输入标签:B
请输入等级:15
请输入颜色:
白
请输入你的选择:
1.使用baseDMA类 2.使用lackDMA类 3.使用hasDMA类
选择->3
请输入标签:C
请输入等级:20
请输入风格:清爽
**********
label:A
**********
label:B
color:白
**********
label:C
style:清爽
请按任意键继续. . .

 

 

 

 

 

 

4.Benevolent Order of Programmers用来维护瓶装葡萄酒箱。为描述它,BOP Portmaster设置了一个Port类,并声明如下:

#include<iostream>

using namespace std;

class Port

{
private:

char * brand;

char style[20]; //i.e., tawny, ruby, vintage

int bottles;

public:

Port(const char * br= "none", const char *st = "none", int b =0);

Port(const Port & p); //copy constructor

virtual ~Port() { delete [] brand; }

Port & operator=(const Port&p);

Port & operator+=(int b); //add b to bottles

Port & operator-=(int b); //subtracts b from bottles , if available

int BottleCount() const {return bottles; ]

virtual void Show() const;

friend ostream & operator<<(ostream & os, const Port &p);

};

show()方法按下面的格式显示信息:

Brand: Gallo

Kind: tawny

Bottles: 20

operator<<()函数按下面的格式显示信息(末尾没有换行符):

Gallo, tawny, 20

PortMaster完成了Port类的方法定义后派生了VintagePort类,然后被解职——因为不小心将一瓶45Cockburn泼到了正在准备烤肉调料的人身上,VintagePort类如下显示:

class VintagePort: public Port //style necessarily = "vintage"

{

private:

char * nickname; //i.e. , "The Noble" or "Old Velvet", etc.

int year; //vintage year

public:

VintagePort();

VintagePort(const char * br, const char *st, int b, const char * nn, int y);

//注:我认为上面这个构造函数少了一个st字符串,这个字符串是用于给style字符串赋值的

VintagePort(const VintagePort & vp);

~VintagePort() { delete [] nickname; }

VintagePort & operator = (const VintagePort & vp);

void show() const;

friend ostream & operator <<(ostream & os, const VintagePort &vp);

};

您被制定指定负责完成VintagePort。

a。第一个任务是重新创建Port方法定义,因为前任被开除时销毁了方法定义。

b。第二个任务是解释为什么有的方法重新定义了,而有些没有重新定义。

c。第三个任务解释为何没有将operator=() operator<<()声明为虚的。

d。第四个任务是提供VintagePort中各个方法的定义。

 

答:

②对于基类的虚函数,有必要重新定义;

③因为赋值运算符和友元函数不能被继承;

代码:

//port.h
#include<iostream>
using namespace std;
class Port
{
private:
	char * brand;
	char style[20];	//i.e., tawny, ruby, vintage
	int bottles;
public:
	Port(const char * br = "none", const char *st = "none", int b = 0);
	Port(const Port & p);		//cpoy constructor
	virtual ~Port() { delete[] brand; }
	Port & operator=(const Port&p);
	Port & operator+=(int b);		//add b to bottles
	Port & operator-=(int b);		//subtracts b from bottles , if available
	int BottleCount() const { return bottles; }
	virtual void Show() const;
	friend ostream & operator<<(ostream & os, const Port &p);
};

class VintagePort : public Port		//style necessarily = "vintage"
{
private:
	char * nickname;		//i.e. , "The Noble" or "Old Velvet", etc.
	int year;				//vintage year
public:
	VintagePort();
	VintagePort(const char * br, const char *st, int b, const char * nn, int y);
	VintagePort(const VintagePort & vp);
	~VintagePort() { delete[] nickname; }
	VintagePort & operator = (const VintagePort & vp);
	void show() const;
	friend ostream & operator <<(ostream & os, const VintagePort &vp);
};

//port.cpp
#include<iostream>
#include"port.h"
using namespace std;

//Port类
Port::Port(const char * br, const char *st, int b)
{
	brand = new char[strlen(br) + 1];
	strcpy_s(brand, strlen(br) + 1, br);
	strcpy_s(style, strlen(st) + 1, st);
	bottles = b;
}
Port::Port(const Port & p)		//copy constructor
{
	brand = new char[strlen(p.brand) + 1];
	strcpy_s(brand, strlen(p.brand) + 1, p.brand);
	strcpy_s(style, strlen(p.style) + 1, p.style);
	bottles = p.bottles;
}
Port & Port::operator=(const Port&p)
{
	if (this == &p)return *this;
	delete[]brand;
	brand = new char[strlen(p.brand) + 1];
	strcpy_s(brand, strlen(p.brand) + 1, p.brand);
	strcpy_s(style, strlen(p.style) + 1, p.style);
	bottles = p.bottles;
	return *this;
}
Port & Port::operator+=(int b)		//add b to bottles
{
	bottles += b;
	return *this;
}
Port & Port::operator-=(int b)		//subtracts b from bottles , if available
{
	bottles -= b;
	return *this;
}
void Port::Show() const
{
	cout << "Brand: " << brand << endl;
	cout << "Kind: " << style << endl;
	cout << "Bottles: " << bottles << endl;
}
ostream & operator<<(ostream & os, const Port &p)
{
	os << p.brand << ", " << p.style << ", " << p.bottles;
	return os;
}

//VintagePort类
VintagePort::VintagePort() :Port()
{
}
VintagePort::VintagePort(const char * br, const char *st, int b, const char * nn, int y) : Port(br, st, b)
{
	nickname = new char[strlen(nn) + 1];
	strcpy_s(nickname, strlen(nn) + 1, nn);
	year = y;
}
VintagePort::VintagePort(const VintagePort & vp) :Port(vp)
{
	nickname = new char[strlen(vp.nickname) + 1];
	strcpy_s(nickname, strlen(vp.nickname) + 1, vp.nickname);
	year = vp.year;
}
VintagePort & VintagePort::operator = (const VintagePort & vp)
{
	if (this == &vp)return *this;
	Port::operator=(vp);
	delete[]nickname;
	nickname = new char[strlen(vp.nickname) + 1];
	strcpy_s(nickname, strlen(vp.nickname) + 1, vp.nickname);
	year = vp.year;
	return *this;
}
void VintagePort::show() const
{
	Port::Show();
	cout << "Nickname: " << nickname << endl;
	cout << "Year: " << year << endl;
}
ostream & operator <<(ostream & os, const VintagePort &vp)
{
	os << (const Port&)vp;
	os << ", " << vp.nickname << ", " << vp.year;
	return os;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值