我们先来看一段简单代码,A类有一个指针成员_pa,B类公有继承了A类,然后自己有一个指针成员_pb:
class A{ public: A(int x = 1) :_pa(new int(x)) {} ~A() { cout << "~A()" << endl; } protected: int* _pa; }; class B : public A{ public: B(int b) :A(b) ,_pb(new int(b)) {} ~B() { cout << "~B()" << endl; } protected: int* _pb; };
如果不把父类的析构函数定义为虚函数,会有什么问题?
void Test()
{
A* pa = new B(0);//父类的指针指向了子类的对象
delete pa;//
}
pa是A类的指针,它指向了新创建的B类对象,在析构时,理应调用B类的析构函数,然后执行结果是调用了A类的析构函数:
原因就是,没有构成多态,与类型有关,因为pa是父类的指针,就一定调用的是父类的析构函数。
但如果把A类的析构函数定义为虚函数:
......
virtual ~A()
{
cout << "~A()" << endl;
}
......
问题是,父子的析构函数名字不相同,就算我加了virtual使父类的析构函数变为虚函数,也不会被子类重写啊。
其实,析构函数是一个特殊的函数,编译器在编译时,析构函数的名字统一为destucter,所以只要父类的析构函数定义为虚函数,不管子类的析构函数前是否加virtual(可以理解为编译器优化),都构成重写。
再看刚才的问题:
void Test()
{
A* pa = new B(0);//父类的指针指向了子类的对象
delete pa;//
}
父类的指针指向了子类的对象,然后调用重写虚函数——析构函数,不就构成了多态嘛,而多态与类型无关,只与对象有关,所以调用的就是子类的析构函数了。
————————————————
原文链接:https://blog.csdn.net/han8040laixin/article/details/81704165