动态内存分配:
①派生类不使用new
Q:是否需要为派生类重新定义复制构造函数,复制运算符,析构函数?
A:不需要,子类中默认的复制构造函数,复制赋值运算符,析构函数就能完成所有的工作,虽然是浅层
复制,但是由于子类中没有申请动态内存,子类默认的复制构造函数,复制赋值运算符,析构函数都将
自动调用父类的复制构造函数,复制赋值运算符,析构函数,而父类的这些成员都是深复制的即可
②派生类使用new
Q:是否需要为派生类重新定义复制构造函数,复制运算符,析构函数?
A:需要!!
(Ⅰ)如何定义派生类复制构造函数
初始化列表显式调用基类的复制构造函数,并执行派生类新增数据的深度复制
Base::Base(const Base & o)
{
str = new char[std::strlen(o.str)+1];
std::strcpy(str,o.str);
}
Sub::Sub(const Sub & o) : Base(o)//显式调用基类的复制构造函数
{ 下面是派生类成员的深度复制
sub_str = new char[std::strlen(o.sub_str)+1];
std::strcpy(sub_str,o.sub_str);
}
假设sub_str是派生类的新增的指针成员,str是基类的指针成员,子类的复制构造函数显式调用父类的
复制构造函数,对派生类的成员执行深度复制即可
(Ⅱ)如何定义派生类复制赋值运算符
Base & Base::operator=(const Base & o)
{
if(this!=&o)
{
delete[] str;
str = new char[std::strlen(o.str)+1];
std::strcpy(str,o.str);
}
return *this;
}
Sub & Sub::operator=(const Sub & o)
{
if(this==&o)
{
delete[] sub_str;
/*#1*/Base::operator=(o);显式使用基类的复制赋值运算符,完成基类成员的深度复制,*this是隐藏调用者
/*#2*/或者这样this->Base::operator=(o);
/*#3*/*this = o;绝对不能这样做,因为隐式调用了子类的复制赋值运算符,无限递归!!!
sub_str = new char[std::strlen(o.sub_str)+1];
std::strcpy(sub_str,o.sub_str);
}
return *this;
}
#1和#2选其一就行,绝对不能选#3的代码
(Ⅲ)如何定义派生类析构函数
在析构函数里面delete派生类里面的动态内存即可,然后派生类的析构函数会自动调用基类的析构函数
,一般来说,基类的析构函数只要也有delete基类的动态内存,就没有任何问题了
但是要注意:和构造函数的调用顺序不同,析构函数是先调用派生类的,再调用基类的析构函数!!
Base::~Base()
{
delete[] str;
}
Sub::~Sub()
{
delete[] sub_str;
隐式执行基类析构函数
}
③析构多继承派生类
(Ⅰ)非虚继承
#include <iostream>
using namespace std;
class Base
{
private:
int a;
public:
Base(int c = 0) { a = c; cout << "using Base::Base" << endl; }
virtual void f() { cout << "using Base::f" << endl; }
virtual ~Base() { cout << "using Base destructor." << endl; }
};
class Mid_1 :public Base
{
private:
int a;
public:
Mid_1(int _a = 1, int b = 0) :
Base(b), a(_a)
{
cout << "using Mid_1::Mid_1" << endl;
}
~Mid_1() { cout << "using mid_1::~Mid_1" << endl; }
void f() { cout << "using mid_1::f" << endl; }
};
class Mid_2 :public Base
{
private:
int a;
public:
void f() { cout << "using mid_2::f" << endl; }
Mid_2(int _a = 2, int b = 1) :
Base(b), a(_a)
{
cout << "using Mid_2::Mid_2" << endl;
}
~Mid_2() { cout << "using mid_2::~Mid_2" << endl; }
};
class D :public Mid_1, public Mid_2
{
private:
int x;
public:
D(int _x, int m_1, int m_2) :
Mid_1(m_1),
Mid_2(m_2),
x(_x) {
cout << "using D::D" << endl;
}
~D() { cout << "using D::~D" << endl; }
void func()
{
Mid_1::f();
}
};
int main()
{
D d(1, 2, 3);
// d.func();
return 0;
}
菱形继承
d对象里面先调用Mid_1,创建一个Base对象a,接着创建Mid_1,()
然后调用Mid_2,创建Base对象b,接着创建Mid_2,
最后,创建D对象,D对象含有2个Base的对象,并且先创建a后创建b
所以析构的时候先析构b后析构a,析构顺序从派生类到基类析构
(Ⅱ)虚拟多继承
#include <iostream>
using namespace std;
class Top {
public:
Top() { cout << "using Top::Top\n"; }
};
class Base : public Top
{
private:
int a;
public:
Base(int c = 0) { a = c; cout << "using Base::Base" << endl; }
virtual void f() { cout << "using Base::f" << endl; }
virtual ~Base() { cout << "using Base destructor." << endl; }
};
class Mid_1 :virtual public Base
{
private:
int a;
public:
Mid_1(int _a = 1, int b = 0) :
Base(b), a(_a)
{
cout << "using Mid_1::Mid_1" << endl;
}
~Mid_1() { cout << "using mid_1::~Mid_1" << endl; }
void f() { cout << "using mid_1::f" << endl; }
};
class Mid_2 :virtual public Base
{
private:
int a;
public:
void f() { cout << "using mid_2::f" << endl; }
Mid_2(int _a = 2, int b = 1) :
Base(b), a(_a)
{
cout << "using Mid_2::Mid_2" << endl;
}
~Mid_2() { cout << "using mid_2::~Mid_2" << endl; }
};
class D :virtual public Mid_1, virtual public Mid_2
{
private:
int x;
public:
D(int _x, int m_1, int m_2) :
Mid_1(m_1),
Mid_2(m_2),
x(_x) {
cout << "using D::D" << endl;
}
void f(){
}
~D() { cout << "using D::~D" << endl; }
void func()
{
Mid_1::f();
Mid_2::f();
}
};
int main()
{
D d(1, 2, 3);
// d.func();
return 0;
}
D沿着2条路径继承了Base总共2次,所以虚拟继承时,D对象里面只保留了1个Base类的 对象,创建Mid_1和Mid_2的对象前先把他们的共同基类对象创建,接着按照继承顺序来创建对象,所以先创建了Base,Mid_1,Mid_2最后创建D,先析构D,后析构Mid_2,Mid_1,再析构Base