c++子类析构函数未调用
为什么父类的析构函数定义成virtual后, delete pTest2 就会释放Derived的资源, 否则就只能释放Base的资源, 而delete pTest1就能释放Derived 和Base的资源
class Base
{
public:
~Base() {
cout << "Base destructor!" << endl;
};
};
class Derived: public Base
{
public:
~Derived() {
cout << "Derived destructor!" << endl;
};
};
int main() {
Derived *pTest1 = new Derived();
Base *pTest2 = new Derived();
delete pTest1;
delete pTest2;
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
delete的语义就是调用析构函数
如果析构函数有virtual修饰,C++保证delete调用子类析构,插在析构前面。
本身一个delete一个指针只会调用本身的析构。
仔细看这个代码,执行delete pTest2时,编译器并不知道pTest2指向的是一个Base子类!他只知道指向的是类Base!
只能说 cpp 就是这么设计的. 你可说它(被)设计的不好.
sf上有个问题:什么时候不用 virtual destructor?
供参考
https://stackoverflow.com/que...
虚函数意味着每个分配的对象都会通过虚函数表指针增加内存开销。
因此,如果您的程序涉及分配大量的某些对象,那么为了节省每个对象的额外32位,值得避免所有虚函数。
在所有其他情况下,您将节省自己的调试痛苦,使析构函数虚拟化。
以下只是个人理解,如有谬误请指出,谢谢。
首先需要明确两个概念:
第一个是 virtual 的意义,
当我们通过指针调用一个类对象的方法时,编译器只有指针类型和指向地址这两个信息,它只能根据指针类型来推断指向的对象实例在内存里实际长什么样,
当我们调用的是一个 non-virtual 方法时,C++ 只能根据指针类型来判断应该调用的方法,如果这个指针是一个基类指针,即使它指向的是一个子类对象,但编译器不知道啊,所以它只会调用基类中的对应方法。
只有声明了 virtual,C++ 才会在对象实例中创建一个 virtual table,里面包含了这个类对象实际持有的所有 virtual 函数的地址,此时我们通过一个基类指针指向子类对象,调用 virtual 方法,C++ 会到这个虚函数表中调用对应位置的函数指针,自然就能正确调用子类的方法了。
第二个是析构函数的运作方式,
当我们调用一个 class 的析构函数,从这个 class 起,依次往上,每个 base class 的析构函数都会逐个被调用。
这也是为什么 delete 子类指针,子类和父类的析构函数都会被正确调用的原因。
显然,当一个 derived class 对象,经由一个 base class 指针删除时,
如果这个 base class 的析构函数是 non-virtual 的,C++ 就会直接调用 base class 的析构函数,derived class 的析构函数自然得不到执行,
当这个 base class 的析构函数是 virtual 的,C++ 在 vtbl 中找到这个对象实例所持有析构函数的函数指针,并调用它,然后根据析构函数的基本运作方式,子类先调用,基类后调用。