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

时间:2014-08-09 15:41:27

标签: c++ inheritance

我是新手,我知道这是一个非常基本的概念,也可能是重复的。 一旦构造函数被调用,它的相应析构函数是否必须被调用? [代码在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;
}

GIVES OUTPUT

Base Constructor
Derived Constructor
Base Destructor

2 个答案:

答案 0 :(得分:6)

您的代码有未定义的行为。基类的析构函数必须为virtual,以便以下内容具有已定义的行为。

Base* b = new Derived;    
delete b;

来自C ++标准:

  

5.3.5删除

     

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

因此,在您的情况下,静态类型为Base,动态类型为Derived。所以Base的析构函数应该是:

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

答案 1 :(得分:2)

如果它是微不足道的话,就不需要调用析构函数。

但是在你的例子中没有用,因为如果一个类有一个带有非平凡析构函数(成员或基础)的子对象,或者它自己的析构函数是用户定义的,那么这不是一件容易的事。

此外,你可能只使用指向base的指针删除一个类,如果那个基类有一个virtual析构函数,那就是undefined behavior(编译器不需要警告你)。

Pro-tip:如果您需要将其设置为虚拟(例如由于上述要求),但又不想阻止它变得微不足道(某些容器和算法已针对普通类型优化了实现),请使用:

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

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