/*
构造函数为什么不能设置为虚函数?
1构造函数构造完成,对象才产生,不符合要求2
2构造函数中(调用的任何虚函数),不会发生动态绑定,都是静态绑定
正常的父子构造:
子类对象先调用父类构造,再调用子类的构造函数
如果强行virtual+构造:
当子类对象构造时,先调用父类的virtual构造函数,此时子类对象还没构造完成
若在父类构造中发生动态绑定则返回调用子类的构造函数,而此时子类还没初始化完成无法调用
注意:static+virtual也不行,因为static成员不依赖于对象,不符合要求2
而析构函数可以设置为virtual
为什么需要将析构函数声明为virtual?
例如p2,虽然delete了父类指针p2(静态绑定~base())
但失去调用子类析构的可能,会导致内存泄漏
解决办法就是虚析构函数,父类设置虚析构,子类自动变为虚析构
因为父类中存在virtual时发生动态绑定,p2指向子类类型
当delete p2时,会先调用子类析构函数,作用域结束再父类析构
什么时候需要把父类析构函数声明为虚函数?
当父类指针/引用指向堆上new出来的子类对象的时候,此时必须手动delete
调用析构函数时必须发生动态绑定,否则无法调用子类析构函数导致资源无法释放
*/
class base
{
private:
int fu;
public:
base(int val) :fu(val) { cout << "父类构造函数" << endl; }
virtual ~base() { cout << "~父类析构函数" << endl; }
};
// 继承了父类的虚函数&base::~base,并重写~base,此时vftable中只含有&derive::~derive
class derive :public base
{
private:
int zi;
int* ptr = nullptr; // 如果没有调用子类的析构函数,会使ptr所指向的资源无法被释放
public:
derive(int val) :base(val), zi(val) { cout << "子类构造函数" << endl; }
~derive() { cout << "~子类析构函数" << endl; }
};
int main()
{
//derive a(10);
//base* p1 = &a; // 正常调用父子析构构造
base* p2 = new derive(10); // 在堆上创建,此时顺手打印两个构造函数
delete p2; // 此时发现并没有调用子类的析构函数,这会导致内存泄漏
return 0;
}