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