我为它创建了派生类的对象和基类点, 然后我使用dynamic_cast转换基类指向派生类点。 我删除派生类的点,但程序调用派生的析构函数和基础析构函数。为什么程序会调用基础析构函数?毕竟,基础析构函数不是虚函数....
#include<iostream>
#include<stdlib.h>
using namespace std;
class con {
private:
double num;
public:
con() {
num = 0;
cout << "default..." << endl;
}
void getnum() {
cout << num << endl;
}
};
class base {
public:
virtual void A() {
cout << "it is base A" << endl;
}
void B() {
cout << "it is base B" << endl;
}
~base() {
cout << "it is base decon" << endl;
}
};
class child : public base {
public:
void A() {
cout << "it is child A" << endl;
}
void B() {
cout << "it is child B" << endl;
}
~child() {
cout << "it is child decon" << endl;
}
};
int main(int argc, char** argv) {
base* b = new child();
child* c = dynamic_cast<child*>(b);
delete c; //the program print "it is child decon" "it is base decon"
getchar();
return 0;
}
答案 0 :(得分:1)
情况1:如果删除指针派生类,它总是首先调用派生类的析构函数,然后调用基类的析构函数。
案例2:如果使用 非虚拟 基类析构函数删除指向派生类的基类的指针,则它不知道派生的class所以它只删除基类。
案例3:如果使用 虚拟 基类析构函数删除指向派生类的基类的指针,它会使用虚拟派发到派生的析构函数class,然后调用基类的析构函数。
案例2很糟糕。它可能导致资源泄漏等。应该通过始终在要作为基类的类中声明虚拟析构函数来避免它。
您的示例说明了案例1。
如果您想要查看案例2,请在示例中尝试delete b
而不是delete c
。
答案 1 :(得分:0)
C ++中的析构函数不会超载&#34;因此;他们连锁起来。当你说
{
child c;
}
然后在结束括号中,编译器将插入对~child()
的调用,该调用将依次调用~base()
(以及其他基类的析构函数,如果有的话)。这对于避免内存泄漏至关重要 - 否则base
的成员将如何被销毁?请注意,这并不要求base
析构函数为virtual
。
当您使用delete
手动销毁某些内容时,此方法的工作方式相同:
child* c = new child{};
delete c; // runs ~child(), which calls ~base()
再次,这并不要求析构函数为virtual
。
虚拟析构函数做所做的是允许您使用指向child
的指针来销毁动态类型为base
的变量,即
child* c = new child{}
base* b = c;
delete b; // Will call ~child() if destructor is virtual, otherwise ~base()