C++primer plus第六版课后编程练习答案13.2

#ifndef CD_H_
#define CD_H_

struct StrAndLen
{
	char *ch;
	int len;
};

//base class
class Cd{//represents a CD disk
private:
	StrAndLen performers;
	StrAndLen label;
	int selections;//number of selections
	double playtime;//playing time in minutes
public:
	char *perfor()const{return performers.ch;}
	char *lab()const{return label.ch;}
	int sel()const{return selections;}
	double pla()const{return playtime;}
    void setPer(char *p);  
    void setlab(char *l);
    void setsel(int num){selections=num;};  
    void setplay(double s){playtime=s;};  

	void setchar(StrAndLen &s,const char *c);
	void delchar(StrAndLen &s);

	Cd(char *s1,char *s2,int n,double x);
	Cd(const Cd &d);
	Cd(){performers.ch=NULL;label.ch=NULL;}//传递给delete的指针必须指向动态分配的内存,或是一个空指针,所以,为了防止delete野指针出错,先将指针置为空
	virtual ~Cd();
	virtual void Report()const;//report all CD data
	virtual Cd &operator=(const Cd &d);
};

class Classic:public Cd
{
private:
	StrAndLen works;
public:
	Classic(char *w,char *s1,char *s2,int n,double x);
	Classic(const Classic &c);
	Classic(){works.ch=NULL;}
	virtual ~Classic();
	virtual void Report()const;
	virtual Classic &operator=(const Classic &c);
};

#endif
#include <iostream>
#include "Cd.h"

using namespace std;


Cd::Cd(char *s1,char *s2,int n,double x)
{	
	setchar(performers,s1);
	setchar(label,s2);
	selections=n;
	playtime=x;
}

Cd::Cd(const Cd &d)
{
	setchar(performers,d.performers.ch);//常对象会将它的方法强行转换为常方法,导致匹配不到对应方法
	setchar(label,d.label.ch);

	selections=d.selections;
	playtime=d.playtime;
}

Cd::~Cd()
{
	delete [] performers.ch;
	delete [] label.ch;

	performers.ch=NULL;
	label.ch=NULL;

	performers.len=0;
	label.len=0;

	selections=playtime=0;

}

void Cd::setPer(char *p)
{
	delchar(performers);
	setchar(performers,p);
}
   
void Cd::setlab(char *l)
{
	delchar(label);
	setchar(label,l);
}

void Cd::setchar(StrAndLen &s,const char *c)
{
	s.len=strlen(c);
	s.ch=new char[s.len+1];
	strcpy(s.ch,c);
}

void Cd::delchar(StrAndLen &s)
{
//	s.ch=NULL;//先将指针置空再delete的做法会导致内存泄露,就是先前new的那块内存的地址找不到了,无法释放,导致系统在程序运行期间无法调用这块内存
	//你直接赋值为0,可是之前指针所批的内容还在,系统仍为你的程序保留着之前所批的那块内存,这部分内存你不用了,但其他程序也用不了,也就是内存泄漏了,
	//动态分配的内存需要自己释放,静态分配的内存可以不用释放
	delete [] s.ch;//new了才能delete
	s.ch=NULL;
	s.len=0;
}

void Cd::Report()const
{
	cout<<performers.ch<<" "
		<<label.ch<<" "
		<<selections<<" "
		<<playtime<<" "<<endl;
}

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

	delchar(performers);
	delchar(label);
	
	setchar(performers,d.perfor());//常对象会将它的方法强行转换为常方法,导致匹配不到非const方法的对应方法
	setchar(label,d.lab());

	selections=d.selections;
	playtime=d.playtime;

	return *this;
}

Classic::Classic(char *w,char *s1,char *s2,int n,double x):Cd(s1,s2,n,x)
{
	setchar(works,w);
}

Classic::Classic(const Classic &c):Cd(c.perfor(),c.lab(),c.sel(),c.pla())
{
	setchar(works,c.works.ch);
}

Classic::~Classic()
{
	delete [] works.ch;
	works.ch=NULL;
	works.len=0;

	Cd::~Cd();


}

void Classic::Report()const
{
	cout<<works.ch<<" ";
	Cd::Report();//调用父类同名方法
}

Classic & Classic::operator =(const Classic &c)//不能delete没有new的动态数组
{
	if(this==&c)
		return *this;

	delchar(works);
	setchar(works,c.works.ch);
	setPer(c.perfor());
	setlab(c.lab());
	setsel(c.sel());
	setplay(c.pla());

	return *this;
}

#include <iostream>
#include "Cd.h"

using namespace std;

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;//指针pcd析构时会将指向的对像析构,使这个对象析构时出错,解决办法,对象析构时将类中指针置空,空指针可以被多次delete

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

	cout<<"Using type cd * pointer to object:\n";
	pcd->Report();
	pcd=&c2;
	pcd->Report();

	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();
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值