析构函数为什么是虚函数
虚构函数是虚函数的情况只需要在特定场景下出现即可,正常情况下不必要弄成虚函数。
如果基类的析构函数不是虚函数,在特定情况下会导致派生来无法被析构。
情况1:用派生类类型指针绑定派生类实例,析构的时候,不管基类析构函数是不是虚函数,都会正常析构
情况2:用基类类型指针绑定派生类实例,析构的时候,如果基类析构函数不是虚函数,则只会析构基类,不会析构派生类对象,从而造成内存泄漏。为什么???因为析构的时候如果没有虚函数的动态绑定功能,就只根据指针的类型来进行的,而不是根据指针绑定的对象来进行,所以只是调用了基类的析构函数;如果基类的析构函数是虚函数,则析构的时候就要根据指针绑定的对象来调用对应的析构函数了。
构造函数为什么不能出虚函数
因为类的虚函数表指针是在构造函数中初始化的,这时候如果构造函数本身是虚函数,又应该由谁来初始化它的虚函数指针呢,所以构造函数不能是虚函数。
为什么构造函数和析构函数都不能调用虚函数
#include <iostream.h>
using namespace std;
class Base{
public:
Base(){
cout << "Base::Base()\n";
fun();
}
virtual ~Base(){
cout << "Base::Base()\n";
fun();
}
virtual void fun(){
cout << "Base::fun() virtual\n";
}
};
// 派生类
class Derive: public Base{
public:
Derive(){
cout << "Derive::Derive()\n";
fun();
}
~Derive(){
cout << "Derive::Derive()\n";
fun();
}
virtual void fun(){
cout << "Derive::fun() virtual\n";
}
};
int main()
{
Base *bd = new Derive(); // 基类Base的指针bd指向的是派生类Derive的对象
delete bd;
return 0;
}
对于上述情况,基类指针指向派生类对象。构造时,先调用基类Base的构造函数,此时构函数中调用基类中的fun()函数,此时虚函数的动态绑定机制并没有会生效,这是因为此时的派生类还不存在。析构时,先析构派生类,派生类中的fun()函数调用的是自己的fun(),然后析构基类Base,基类析构函数中的fun()调用的是基类Base自己的fun()函数,这里虚函数的动态绑定机制也没有生效,因为此时派生类已经不存在了。
- 不要在构造函数中调用虚函数的原因:因为父类对象会在子类之前进行构造,此时子类部分的数据成员还未初始化, 因此调用子类的虚函数是不安全的,故而C++不会进行动态联编。
- 不要在析构函数中调用虚函数的原因:析构函数是用来销毁一个对象的,在销毁一个对象时,先调用子类的析构函数,然后再调用基类的析构函数。所以在调用基类的析构函数时,派生类对象的数据成员已经“销毁”,这个时再调用子类的虚函数已经没有意义了。