一.基类与派生类之间的转换
- 可以把派生类赋值给基类
- 可以把基类引用绑定派生类对象
- 可以把基类指针指向派生类对象
#include <iostream>using std::cin;
using std::cout;
using std::endl;//基类与派生类相互转化
class Base
{
private:int _x;
public:Base(int x=0):_x(x){cout<<"Base()"<<endl;}~Base(){cout<<"~Base()"<<endl;}void show(){cout<<"_x ="<<_x<<endl;}
};class Derived:public Base
{private:int _y;public:Derived(int x=0,int y=0):Base(x),_y(y){cout<<"Derived()"<<endl;}~Derived(){cout<<"~Derived()"<<endl;}void show(){cout<<"_y ="<<_y<<endl;}
};void test()
{Base base(3);Derived derived(5,4);derived.show();base.show();cout<<"派生类向基类转换"<<endl;base=derived;base.show();derived.show();Base& base1=derived;Base* base2=&derived;base1.show(); base2->show();Base base3=derived;}int main()
{test();return 0;}
当派生类转换为基类时,派生类将初始完基类的数据成员再赋给基类。如果需要将基类转换为派生类需要加强制类型转换。
二.派生类间的复制控制
如果基类实现了拷贝构造函数或赋值运算符函数,但是派生类没有实现拷贝构造函数或赋值运算符函数,那么在将一个已经存在的派生类对象初始化一个刚刚创建的派生类对象会调用拷贝构造函数,或者进行两个对象进行赋值时调用赋值运算符函数,由于派生类没有拷贝构造函数那么派生部分就会执行缺省行为,而基类部分会调用基类的构造函数和赋值运算符函数。
1.当派生类无新数据成员时
#include <iostream>
#include <string.h>
using std::cout;
using std::endl;class Base
{
private:char* _pbase;
public:Base(const char* str):_pbase(new char[strlen(str)+1]()){cout<<"Base(const char* str)"<<endl;strcpy(_pbase,str);}~Base(){cout<<"~Base()"<<endl;if(_pbase!=nullptr){delete[]_pbase;_pbase=nullptr;}}Base():_pbase(nullptr){cout<<"Base()"<<endl;}Base(const Base& rhs):_pbase(new char[strlen(rhs._pbase)+1]()){cout<<"Base(const Base& rhs)"<<endl;strcpy(_pbase,rhs._pbase);}Base& operator=(const Base& rhs){//自复制if(this != &rhs){cout<<"Base& operator=(const Base& rhs)"<<endl;if(_pbase!=nullptr){delete[] _pbase;_pbase=nullptr;}_pbase=new char[strlen(rhs._pbase)+1]();strcpy(_pbase,rhs._pbase);}return *this;}friend std::ostream& operator<<(std::ostream& os,const Base& rhs);};class Derived
: public Base
{public:Derived(const char* str1):Base(str1){cout<<"Derived(const char* str1)"<<endl;}~Derived(){cout<<"~Derived()"<<endl;}friend std::ostream& operator<<(std::ostream& os,const Derived& rhs);
};std::ostream& operator<<(std::ostream& os,const Derived& rhs)
{const Base &base=rhs;os<<base;return os;
}
std::ostream& operator<<(std::ostream& os,const Base& rhs)
{if(rhs._pbase){os<<rhs._pbase;}return os;
}void test()
{Derived derived("hello");cout<<"derived = "<<derived<<endl;cout<<endl;Derived derived1(derived);cout<<"derived = "<<derived<<endl;cout<<"derived1 = "<<derived1<<endl;cout<<endl;Derived derived2("你好");cout<<"derived2 = "<<derived2<<endl;cout<<endl;derived2=derived;cout<<"derived = "<<derived<<endl;cout<<"derived2 = "<<derived2<<endl;
}int main()
{test();return 0;
}
2.当派生类有新数据成员时
#include <iostream>
#include <string.h>
using std::cout;
using std::endl;class Base
{
private:char* _pbase;
public:Base(const char* str):_pbase(new char[strlen(str)+1]()){cout<<"Base(const char* str)"<<endl;strcpy(_pbase,str);}~Base(){cout<<"~Base()"<<endl;if(_pbase!=nullptr){delete[]_pbase;_pbase=nullptr;}}Base():_pbase(nullptr){cout<<"Base()"<<endl;}Base(const Base& rhs):_pbase(new char[strlen(rhs._pbase)+1]()){cout<<"Base(const Base& rhs)"<<endl;strcpy(_pbase,rhs._pbase);}Base& operator=(const Base& rhs){//自复制if(this != &rhs){cout<<"Base& operator=(const Base& rhs)"<<endl;if(_pbase!=nullptr){delete[] _pbase;_pbase=nullptr;}_pbase=new char[strlen(rhs._pbase)+1]();strcpy(_pbase,rhs._pbase);}return *this;}friend std::ostream& operator<<(std::ostream& os,const Base& rhs);
};class Derived
: public Base
{
private:char* _pderived;
public:Derived(const char* str1,const char* str2):Base(str1),_pderived(new char[strlen(str2)+1]()){cout<<"Derived(const char* str1,const char* str2)"<<endl;strcpy(_pderived,str2);}Derived(const Derived& rhs):_pderived(new char[strlen(rhs._pderived)+1]()){cout<<"Derived(const Derived& rhs)"<<endl;strcpy(_pderived,rhs._pderived);}Derived& operator=(const Derived& rhs){cout<<"Derived& operator=(const Derived& rhs)"<<endl;if(this != &rhs){if(_pderived!=nullptr){delete[]_pderived;_pderived=nullptr;}_pderived=new char[strlen(rhs._pderived)+1]();strcpy(_pderived,rhs._pderived);}return *this;}~Derived(){cout<<"~Derived()"<<endl;if(_pderived!=nullptr){delete[]_pderived;_pderived=nullptr;}}friend std::ostream& operator<<(std::ostream& os,const Derived& rhs);
};std::ostream& operator<<(std::ostream& os,const Derived& rhs)
{const Base &base=rhs;os<<base<<" , "<<rhs._pderived;return os;
}
std::ostream& operator<<(std::ostream& os,const Base& rhs)
{if(rhs._pbase){os<<rhs._pbase;}return os;
}
void test()
{Derived derived("hello","world");cout<<"derived = "<<derived<<endl;cout<<endl;Derived derived1(derived);cout<<"derived = "<<derived<<endl;cout<<"derived1 = "<<derived1<<endl;cout<<endl;Derived derived2("你好","世界");cout<<"derived2 = "<<derived2<<endl;cout<<endl;derived2=derived;cout<<"derived = "<<derived<<endl;cout<<"derived2 = "<<derived2<<endl;
}int main()
{test();return 0;
}
如果基类和派生类都实现了拷贝构造函数和赋值运算符函数,那么在将一个已经存在的派生类对象初始化一个刚刚创建的派生类对象,或者两个派生类对象进行赋值时,派生类数据成员部分会执行派生类自己的拷贝构造函数或赋值运算符函数,而基类部分不会执行基类的拷贝构造函数或赋值运算符函数,除非在派生类中显示的调用基类的拷贝与赋值。
3.改进
#include <iostream>
#include <string.h>
using std::cout;
using std::cin;
using std::endl;class Base
{
private:char* _pbase;
public:Base(const char* str):_pbase(new char[strlen(str)+1]()){cout<<"Base(const char* str)"<<endl;strcpy(_pbase,str);}~Base(){cout<<"~Base()"<<endl;if(_pbase!=nullptr){delete[]_pbase;_pbase=nullptr;}}Base():_pbase(nullptr){cout<<"Base()"<<endl;}Base(const Base& rhs):_pbase(new char[strlen(rhs._pbase)+1]()){cout<<"Base(const Base& rhs)"<<endl;strcpy(_pbase,rhs._pbase);}Base& operator=(const Base& rhs){//自复制if(this != &rhs){cout<<"Base& operator=(const Base& rhs)"<<endl;if(_pbase!=nullptr){delete[] _pbase;_pbase=nullptr;}_pbase=new char[strlen(rhs._pbase)+1]();strcpy(_pbase,rhs._pbase);}return *this;}friend std::ostream& operator<<(std::ostream& os,const Base& rhs);};class Derived
: public Base
{
private:char* _pderived;
public:Derived(const char* str1,const char* str2):Base(str1),_pderived(new char[strlen(str2)+1]()){cout<<"Derived(const char* str1,const char* str2)"<<endl;strcpy(_pderived,str2);}Derived(const Derived& rhs):Base(rhs) //显示调用拷贝构造函数,_pderived(new char[strlen(rhs._pderived)+1]()){cout<<"Derived(const Derived& rhs)"<<endl;strcpy(_pderived,rhs._pderived);}Derived& operator=(const Derived& rhs){cout<<"Derived& operator=(const Derived& rhs)"<<endl;Base::operator=(rhs);//显示调用赋值运算符函数if(this != &rhs){if(_pderived!=nullptr){delete[]_pderived;_pderived=nullptr;}_pderived=new char[strlen(rhs._pderived)+1]();strcpy(_pderived,rhs._pderived);}return *this;}~Derived(){cout<<"~Derived()"<<endl;if(_pderived!=nullptr){delete[]_pderived;_pderived=nullptr;}}friend std::ostream& operator<<(std::ostream& os,const Derived& rhs);};std::ostream& operator<<(std::ostream& os,const Derived& rhs)
{const Base &base=rhs;os<<base<<" , "<<rhs._pderived;return os;
}
std::ostream& operator<<(std::ostream& os,const Base& rhs)
{if(rhs._pbase){os<<rhs._pbase;}return os;
}void test()
{Derived derived("hello","world");cout<<"derived = "<<derived<<endl;cout<<endl;Derived derived1(derived);cout<<"derived = "<<derived<<endl;cout<<"derived1 = "<<derived1<<endl;cout<<endl;Derived derived2("你好","世界");cout<<"derived2 = "<<derived2<<endl;cout<<endl;derived2=derived;cout<<"derived = "<<derived<<endl;cout<<"derived2 = "<<derived2<<endl;}int main()
{test();return 0;
}