请通过我下面的代码:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class ClassA
{
protected:
int width, height;
public:
void set_values(int x, int y)
{
width = x;
height = y;
}
virtual int area()
{
return 100;
}
~ClassA()
{
cout << "base class destructor called" << endl;
}
};
class ClassB : public ClassA
{
public :
int area()
{
return (width * height);
}
~ClassB()
{
cout << "derived class destructor called" << endl;
}
};
int main()
{
ClassA *Ptr = new ClassB;
Ptr->set_values(10, 20);
cout << Ptr->area() << endl;
delete Ptr;
return 0;
}
在上面的代码中,指针包含派生类对象的地址,因此当我删除指针时,它应与派生类析构函数一起调用派生类析构函数,但为什么它仅调用基类析构函数。如果我将基类析构函数设为虚拟,则为什么同时调用派生类和基类析构函数?在虚函数的情况下,基类和派生类都具有相同的函数名,因此编译器解析派生类中派生最多的一个,但是在这里析构函数将没有相同的名称,然后编译器将解析其必须调用的那个名称在运行时。请给我解释一下
最佳答案
您应该将基类的析构函数设置为virtual
,以便多态破坏能够正常工作:
class ClassA
{
// ...
virtual ~ClassA()
// ^^^^^^^
// Add this!
{
cout << "base class destructor called" << endl;
}
};
如果不这样做,则在执行
delete Ptr
时会得到未定义的行为。如果我将基类析构函数设为虚拟,那么它同时调用派生类和基类析构函数,为什么呢?
这是常规对象销毁序列的一部分。销毁对象时,将首先调用该对象类的析构函数,然后调用该对象的所有非静态类成员的析构函数(以相反的顺序声明),然后调用其所有基类的析构函数。
因此,在这种情况下可以正确执行虚拟调度(当然,如果您使基类的析构函数为
virtual
),则在某种意义上,第一个被调用的析构函数是对象的实际运行时类型的析构函数()。之后,将调用基类ClassB
的析构函数以及正常销毁过程的一部分。但是在这里,析构函数的名称将与编译器如何解析其在运行时必须调用的名称不同。
析构函数是特殊的成员函数。每个类只能有一个析构函数,因此它们的名称(必须与该类的名称相同,并带有前缀
ClassA
字符)是无关紧要的。编译器知道哪个函数是析构函数。关于c++ - C++中的析构函数概念,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15292789/