假设基类base,派生类derive1,derive2. 其中前2者含有指针成员(自动分配内存),后者不含。
1.声明
三者声明如下:
#include"iostream" #include"string" using namespace std; //含有动态分配内存的基类 class base{ public: base(const char* pointer=NULL); base(const base&); base& operator=(const base&); friend ostream& operator <<(ostream& ,const base&); virtual ~base(){ if(p) delete []p; } private: char* p; }; //含有动态分配内存的派生类 class derive1 :public base{ public: derive1(const char* pointer1=NULL,const char* pointr2=NULL); derive1(derive1&); derive1& operator=(const derive1&); friend ostream& operator <<(ostream&,const derive1&); ~derive1(){ if(q) delete []q; } private: char* q; }; //不含动态分配内存的派生类 class derive2 :public base{ public: derive2(const string& ,const char* pointer=NULL); derive2(const derive2&); friend ostream& operator <<(ostream&,const derive2&); private: string q; };
对于基类base: (1)需要重载拷贝构造函数和赋值运算符。 (2)析构函数声明为虚函数。当派生类也具有自动分配内存时,基类指针指向派生类对象时,将调用派生类的析构函数(继而调用基类析构函数)释放所有内存。这样避免了内存泄露
对于derive1:public base的情况: (1)需要重载拷贝构造函数,且显式调用基类拷贝构造函数构造基类部分; (2)需要重载赋值运算符,且其中,使用base::operator=(d);显式地调用基类赋值运算符复制基类部分 (3)倘若需要重载输出运算符。其中需要显式的使用类型转换out<<(const base&)d;输出基类数据,然后再输出派生类的数据
对于derive2:public base的情况: (1)不需要重载拷贝构造函数,其中对于基类的自动分配内存的拷贝自动调用基类中已经重载的拷贝构造函数。 (2)需要在输出运算符重载时,显式转换且输出基类数据。
2.定义
#include"declaration.h" /************************基类base定义*****************************/ base::base(const char* pointer){//构造函数 if(!pointer) p=NULL; else{ p=new char[strlen(pointer)+1]; strcpy(p,pointer); } } base::base(const base& b){//拷贝构造函数 p=new char[strlen(b.p)+1]; strcpy(p,b.p); } base& base::operator=(const base& b){//重载赋值函数 if(this==&b) return *this; if(p){ delete[]p; p=NULL; } p=new char[strlen(b.p)+1]; strcpy(p,b.p); return *this; } ostream& operator <<(ostream& out,const base& b){//重载输出运算符 if(b.p) cout<<b.p<<endl; return out; } /************************含有动态分配内存的派生类derive1的定义*****************************/ derive1:: derive1(const char* pointer1,const char* pointer2):base(pointer1){//构造函数 if(!pointer2) q=NULL; else{ q=new char[strlen(pointer2)+1]; strcpy(q,pointer2); } } derive1:: derive1(derive1& d):base(d){//拷贝构造函数 q=new char[strlen(d.q)+1]; strcpy(q,d.q); } derive1& derive1::operator=(const derive1& d){//重载赋值运算符 if(this==&d) return *this; base::operator=(d); if(q){ delete[]q; q=NULL; } q=new char[strlen(d.q)+1]; strcpy(q,d.q); return *this; } ostream& operator <<(ostream& out,const derive1& d){//重载输出运算符 out<<(const base&)d<<d.q<<endl; return out; } /************************不含有动态分配内存的派生类derive1的定义*****************************/ derive2:: derive2(const string& s,const char*pointer):base(pointer),q(s){}//构造函数 ostream& operator <<(ostream& out,const derive2&d){//重载输出运算符 out<<(const base&)d<<d.q<<endl; return out; }
注意:编译时,只需包含声明文件“declaration.h”即可,否则会显示link2005的重定义错误。