//13.1
//cd.h --- base class
#ifndef CD__H__
#define CD__H__
class Cd
{
private:
char performers[50];//演员
char label[20];//标签
int selections;
double playtime;
public:
Cd(char* s1,char* s2,int n,double x);
//Cd(const Cd & d);
Cd();
virtual ~Cd(){}
virtual void Report() const;
virtual Cd & operator=(const Cd & d);
};
class Classic : public Cd
{
private:
char works[20];
public:
Classic(char* s1,char* s2,char* s3,int n,double x);
Classic();
virtual ~Classic(){}
virtual Classic & operator=(const Classic & c);
};
#endif
//classic.cpp
#include <iostream>
#include "cd.h"
Cd::Cd(char* s1,char* s2,int n,double x)
{
strcpy(performers,s1);
strcpy(label,s2);
selections = n;
playtime = x;
}
//Cd(const Cd & d);
Cd::Cd()
{
strcpy(performers,"NULL");
strcpy(label,"NULL");
selections = 0;
playtime = 0.0;
}
void Cd::Report() const
{
std::cout<<"The performers is "<<performers<<" ,and the label is "
<<label<<" ,the selections is "<<selections
<<" ,the playtime is "<<playtime<<std::endl;
}
Cd & Cd::operator=(const Cd & d)
{
if(this == &d)
return *this;
strcpy(performers,d.performers);
strcpy(label,d.label);
selections = d.selections;
playtime = d.playtime;
return *this;
}
Classic::Classic(char* s1,char* s2,char* s3,int n,double x):Cd(s1,s2,n,x)
{
strcpy(works,s3);
}
Classic::Classic():Cd()
{
strcpy(works,"NULL");
}
Classic & Classic::operator=(const Classic & c)
{
if(this == &c)
return *this;
Cd::operator=(c);
strcpy(works,c.works);
return *this;
}
//main.cpp
#include <iostream>
#include "cd.h"
using namespace std;
void Bravo(const Cd & disk);
int main()
{
Cd c1("Beatles","Capitol",14,25.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();
c2.Report();
cout<<"Using type cd * pointer to objects:\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();//虚函数将根据引用参数指向的实际类型输出
}
//13.2
//cd.h --- base class
#ifndef CD__H__
#define CD__H__
class Cd
{
private:
char* performers;//演员
char* label;//标签
int selections;
double playtime;
public:
Cd(char* s1,char* s2,int n,double x);
Cd(const Cd & d);
Cd();
virtual ~Cd();
virtual void Report() const;
virtual Cd & operator=(const Cd & d);
};
class Classic : public Cd
{
private:
char* works;
public:
Classic(char* s1,char* s2,char* s3,int n,double x);
Classic(const Classic & c);
Classic(char* s3,const Cd & d);
Classic();
virtual ~Classic();
virtual Classic & operator=(const Classic & c);
virtual void Report() const;
};
#endif
//classic.cpp
#include <iostream>
#include "cd.h"
Cd::Cd(char* s1,char* s2,int n,double x)
{
performers = new char[strlen(s1)+1];
strcpy(performers,s1);
label = new char[strlen(s2)+1];
strcpy(label,s2);
selections = n;
playtime = x;
}
Cd::Cd(const Cd & d)
{
performers = new char[strlen(d.performers)+1];
strcpy(performers,d.performers);
label = new char[strlen(d.label)+1];
strcpy(label,d.label);
selections = d.selections;
playtime = d.playtime;
}
Cd::Cd()
{
performers = new char[strlen("NULL")+1];
strcpy(performers,"NULL");
label = new char[strlen("NULL")+1];
strcpy(label,"NULL");
selections = 0;
playtime = 0.0;
}
Cd::~Cd()
{
delete [] performers;
delete [] label;
}
void Cd::Report() const
{
std::cout<<"The performers is "<<performers<<" ,and the label is "
<<label<<" ,the selections is "<<selections
<<" ,the playtime is "<<playtime<<std::endl;
}
Cd & Cd::operator=(const Cd & d)
{
if(this == &d)
return *this;
delete [] performers;
delete [] label;
performers = new char[strlen(d.performers)+1];
strcpy(performers,d.performers);
label = new char[strlen(d.label)+1];
strcpy(label,d.label);
selections = d.selections;
playtime = d.playtime;
return *this;
}
Classic::Classic(char* s1,char* s2,char* s3,int n,double x):Cd(s1,s2,n,x)
{
works = new char[strlen(s3)+1];
strcpy(works,s3);
}
Classic::Classic():Cd()
{
works = new char[strlen("NULL")+1];
strcpy(works,"NULL");
}
Classic::Classic(const Classic & c):Cd(c)
{
works = new char[strlen(c.works)+1];
strcpy(works,c.works);
}
Classic::Classic(char* s3,const Cd & d):Cd(d)
{
works = new char[strlen(s3)+1];
strcpy(works,s3);
}
Classic::~Classic()
{
delete [] works;
}
Classic & Classic::operator=(const Classic & c)
{
if(this == &c)
return *this;
Cd::operator=(c);
delete [] works;
works = new char[strlen(c.works)+1];
strcpy(works,c.works);
return *this;
}
void Classic::Report() const
{
Cd::Report();
std::cout<<"The works is "<<works<<std::endl;
}
//main.cpp
#include <iostream>
#include "cd.h"
using namespace std;
void Bravo(const Cd & disk);
int main()
{
Cd c1("Beatles","Capitol",14,25.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();
c2.Report();
cout<<"Using type cd * pointer to objects:\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();
// personal test
Cd te_cd1 = Cd("mmdnxh","crazy",1,10.0);
Cd te_cd2 = te_cd1;
te_cd2.Report();
Cd te_cd3 = Cd(te_cd2);
te_cd3.Report();
Cd te_cd4;
te_cd4.Report();
Classic te_cl1;
te_cl1.Report();
Classic te_cl2("Jerry",te_cd1);
te_cl2.Report();
Classic te_cl3 = Classic(te_cl2);
te_cl3.Report();
return 0;
}
void Bravo(const Cd & disk)
{
disk.Report();//虚函数将根据引用参数指向的实际类型输出
}
//13.3
//dma.h
#ifndef DMA__H__
#define DMA__H__
#include <iostream>
class Dma
{
private:
int rating;
public:
Dma(int r = 0);
virtual ~Dma();
virtual void View() const = 0;//ABC
};
class baseDma : public Dma
{
private:
char* label;
public:
baseDma(const char* l,int r);
baseDma();
baseDma(const baseDma & ba);
~baseDma();
baseDma & operator=(const baseDma & ba);
void View() const;
};
class lackDma : public Dma
{
private:
char* color;
public:
lackDma();
lackDma(char* c,int r);
lackDma(const lackDma & la);
~lackDma();
lackDma & operator=(const lackDma & la);
void View() const;
};
class hasDma : public Dma
{
private:
char* style;
public:
hasDma();
hasDma(char* c,int r);
hasDma(const hasDma & la);
~hasDma();
hasDma & operator=(const hasDma & la);
void View() const;
};
#endif
#include <iostream>
#include "dma.h"
using std::cin;
using std::cout;
using std::endl;
Dma::Dma(int r)
{
rating = r;
}
Dma::~Dma(){}
void Dma::View() const
{
cout<<"The MDA rating is "<<rating<<endl;
}
baseDma::baseDma(const char* l,int r):Dma(r)
{
label = new char[strlen(l)+1];
strcpy(label,l);
}
baseDma::baseDma():Dma()
{
label = new char[strlen("NULL")+1];
strcpy(label,"NULL");
}
baseDma::baseDma(const baseDma & ba):Dma(ba)
{
label = new char[strlen(ba.label)+1];
strcpy(label,ba.label);
}
baseDma::~baseDma()
{
delete [] label;
}
baseDma & baseDma::operator=(const baseDma & ba)
{
if(this == &ba)
return *this;
delete [] label;
Dma::operator=(ba);//不需要定义基类的显式的复制构造函数
label = new char[strlen(ba.label)+1];
strcpy(label,ba.label);
return *this;
}
//void View() const;
void baseDma::View() const//要重定义继承自基类的方法必须要再次声明覆盖它
{
Dma::View();
cout<<"The DMA label is "<<label<<endl;
}
lackDma::lackDma():Dma()
{
color = new char[strlen("NULL")+1];
strcpy(color,"NULL");
}
lackDma::lackDma(char* c,int r):Dma(r)
{
color = new char[strlen(c)+1];
strcpy(color,c);
}
lackDma::lackDma(const lackDma & la):Dma(la)
{
color = new char[strlen(la.color)+1];
strcpy(color,la.color);
}
lackDma::~lackDma()
{
delete [] color;
}
lackDma & lackDma::operator=(const lackDma & la)
{
if(this == &la)
return *this;
delete [] color;
Dma::operator=(la);//不需要定义基类的显式的复制构造函数
color = new char[strlen(la.color)+1];
strcpy(color,la.color);
return *this;
}
void lackDma::View() const
{
Dma::View();
cout<<"The DMA color is "<<color<<endl;
}
hasDma::hasDma():Dma()
{
style = new char[strlen("NULL")+1];
strcpy(style,"NULL");
}
hasDma::hasDma(char* c,int r):Dma(r)
{
style = new char[strlen(c)+1];
strcpy(style,c);
}
hasDma::hasDma(const hasDma & la):Dma(la)
{
style = new char[strlen(la.style)+1];
strcpy(style,la.style);
}
hasDma::~hasDma()
{
delete [] style;
}
hasDma & hasDma::operator=(const hasDma & ha)
{
if(this == &ha)
return *this;
delete [] style;
Dma::operator=(ha);//不需要定义基类的显式的复制构造函数
style = new char[strlen(ha.style)+1];
strcpy(style,ha.style);
return *this;
}
void hasDma::View() const
{
Dma::View();
cout<<"The DMA style is "<<style<<endl;
}
//usebrass3.cpp
#include <iostream>
#include <string>
#include "dma.h"
const int CLIENTS = 4;
int main()
{
using std::cout;
using std::cin;
using std::endl;
Dma * p_clients[CLIENTS];
std::string temp;
long tempnum;
char str[20];
char kind;
for(int i=0;i< CLIENTS;i++)
{
cout<<"Enter a string type data:";
getline(cin,temp);
strcpy(str,temp.c_str());
cout<<"ENter the rating:";
cin>>tempnum;
cout<<"Enter 1 for baseMda Account ,"
<<" 2 for lackMda Account or 3 for hasDma Account: ";
while(cin>>kind && (kind !='1'&&kind != '2'&&kind != '3'))
cout<<"Enter either 1 or 2 or 3:";
if(kind == '1')
p_clients[i] = new baseDma(str,tempnum);
else if(kind == '2')
{
p_clients[i] = new lackDma(str,tempnum);
}
else
{
p_clients[i] = new hasDma(str,tempnum);
}
while(cin.get()!='\n')
continue;
}
cout<<endl;
for(int i=0;i< CLIENTS;i++)
{
p_clients[i]->View();
cout<<endl;
}
for(int i =0;i< CLIENTS;i++)
{
delete p_clients[i];
}
cout<<"Done!\n";
return 0;
}
//13.4
#ifndef PORT__H__
#define PORT__H__
#include <iostream>
using namespace std;
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 & p);
virtual ~Port() {delete [] brand;}
Port & operator=(const Port & p);
Port & operator+=(int b);
Port & operator-=(int b);
int BottleCount() const {return bottles;}
virtual void Show() const;
friend ostream & operator<<(ostream & os,const Port & p);
};
class VintagePort : public Port
{
private:
char* nickname;
int year;
public:
VintagePort();
VintagePort(const char* br,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);
};
#endif
#include <iostream>
#include "port.h"
Port::Port(const char* br ,const char * st ,int b)
{
brand = new char[strlen(br)+1];
strcpy(brand,br);
int length = strlen(st)>19?19:strlen(st);
strncpy(style,st,length);
if(19 == length)
style[19] = '\0';
else
style[length] = '\0';
bottles = b;
}
Port::Port(const Port & p)
{
brand = new char[strlen(p.brand)+1];
strcpy(brand,p.brand);
strcpy(style,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(brand,p.brand);
strcpy(style,p.style);
bottles = p.bottles;
return *this;
}
Port & Port::operator+=(int b)
{
bottles += b;
return *this;
}
Port & Port::operator-=(int b)
{
int temp = bottles - b;
if(temp<0)
cout<<"The number of inputs is too big,operation concealed!\n";
else
bottles -= b;
return *this;
}
void Port::Show() const
{
cout<<"Brand: "<<brand<<endl
<<"Kind: "<<style<<endl
<<"Bottles: "<<bottles<<endl;
}
ostream & operator<<(ostream & os,const Port & p)
{
os<<p.brand<<", "<<p.style<<", "<<p.bottles;
return os;
}
VintagePort::VintagePort():Port()
{
nickname = new char[strlen("NULL")+1];
strcpy(nickname,"NULL");
year = 0;
}
VintagePort::VintagePort(const char* br,int b,const char* nn,int y):Port(br,"none",b)
{
nickname = new char[strlen(nn)+1];
strcpy(nickname,nn);
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)
{
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;
}
void VintagePort::Show() const
{
Port::Show();
cout<<"Nickname: "<<nickname<<endl
<<"Year: "<<year<<endl;
}
ostream & operator<<(ostream & os,const VintagePort & vp)
{
os<<(const Port &)vp;
os<<", "<<vp.nickname<<", "<<vp.year;
return os;
}
//main.cpp
#include <iostream>
#include "port.h"
int main()
{
Port port1= Port("jerry", "mmd", 1);
Port* ptr = &port1;
Port port2 = Port(port1);
ptr->Show();
cout<<endl;
port2.Show();
cout<<endl;
cout<<port1<<endl;
cout<<endl;
VintagePort v1= VintagePort();
ptr = &v1;
ptr->Show();
cout<<endl;
VintagePort v2 = VintagePort("xxx",1,"yyy",3);
v1 = v2;
cout<<v2 <<endl;
cout<<endl;
return 0;
}
- 从函数中可以看到重新定义了Show()方法,因为基类方法不能满足派生类的功能实现,需要重定义。而对于BottleCount()方法,对于两者而言是等价的,不需要重定义。
- 声明为虚函数的表明派生类要重新定义其继承自基类方法(基类析构函数通常也声明为虚函数,确保析构函数的正确调用),目的在于实现多态。赋值运算符函数是不能继承的,派生类继承的方法的特征标与基类完全相同,但赋值运算符的特征标根据类不同而有所区别。因为它要求的是一个类型为所属类的形参。因此不必声明为虚函数,基类与派生类的赋值运算符函数是独立的,当需要时可以使用作用域解析运算符显式调用。而operator<<()方法是友元函数,亦不能继承。不需要声明为虚函数,需要时将进行强制类型转换。