提问者:小点点

在C继承中,当指向基类的指针对象指向派生类时,不会调用派生类析构函数


我是一个新手,我知道这是一个非常基本的概念,也可能是重复的。一旦调用构造函数,就必须调用相应的析构函数,这不是真的吗?[代码在Dev C上运行]

class Base
    {
     public:
            Base() { cout<<"Base Constructor\n";}
            int b;
     ~Base() {cout << "Base Destructor\n"; }
    };

class Derived:public Base
{
 public:
        Derived() { cout<<"Derived Constructor\n";}
        int a;
 ~Derived() { cout<< "Derived Destructor\n"; }
}; 
int main () {
Base* b = new Derived;    
//Derived *b = new Derived;
 delete b;
    getch();
    return 0;
}

给出输出

Base Constructor
Derived Constructor
Base Destructor

共2个答案

匿名用户

您的代码具有未定义的行为。基类的析构函数必须是虚拟,以下内容才能具有已定义的行为。

Base* b = new Derived;    
delete b;

从C标准:

5.3.5删除

3在第一种选择(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应是操作数动态类型的基类,并且静态类型应具有虚拟析构函数或行为未定义。

所以在你的例子中,静态类型是Base,动态类型是Derive。所以Base的析构函数应该是:

virtual ~Base() {cout << "Base Destructor\n"; }

匿名用户

如果是微不足道的,则无需调用析构函数。

不过,这在您的示例中没有帮助,因为如果一个类有一个具有非平凡析构函数(成员或基)的子对象,或者它自己的析构函数是用户定义的,它就不是平凡的。

此外,如果基类有虚拟析构函数,您只能使用指向base的指针删除类,否则会出现未定义的行为(编译器不需要警告您)。

Pro-tip:如果您需要使其虚拟(例如由于上述要求),但不想阻止它变得琐碎(一些容器和算法针对琐碎类型优化了实现),请使用:

virtual ~MyClass = default; // Since C++11

因此,如果Base没有虚拟析构函数或者它实际上是一个基,则永远不要使用指向Base的指针进行删除。