【问题标题】:how destructor is functioning when deleting a object of one class in other class删除另一个类中一个类的对象时析构函数如何工作
【发布时间】:2019-11-24 20:54:18
【问题描述】:

在下面的代码中,当在destruct类中删除一个基类的对象时,任何类的析构函数都没有被执行。可能是什么原因? “删除 obj”调用的是哪个析构函数?

#include <iostream>
using namespace std;
class base;

class destruct{
    public :
    destruct() {
        cout<<"Destruct Constructor called"<<endl;
    }

    void destructObj(base* obj) {
        delete obj;
    }

    ~destruct() {
        cout<<"Destruct Destructor called"<<endl;
    }
};

class base {
    int runs;
    public:

    base(){

        cout<<"Constructor called"<<endl;
    }

    ~base(){
        cout<<"destructor called"<<endl;
    }
};

int main() {
    base *obj = new base();
    destruct *desObj = new destruct();
    desObj->destructObj(obj);
    return 0;
}

我预计任何类中至少有一个析构函数在运行。 请帮助我了解删除运算符在这种情况下的工作方式。

【问题讨论】:

  • UB。您的析构函数不是虚拟的。编辑:忽略这一点,您只是在删除basebase 的析构函数只被调用,但如果你将 desObj 传递给 destructObj 它将是 UB。
  • 你永远不会 delete desObj 指针,所以该对象不会被破坏。
  • 无论何时何地您 delete obj 指针都无关紧要。在另一个函数中或直接在main 中,它仍然会被删除。也许您显示的代码没有复制您遇到的问题?这真的是一个正确的minimal reproducible example 可以复制您遇到的问题吗?你展示的程序的输出是什么?你期望什么输出?请花点时间刷新how to ask good questions,以及this question checklist
  • @Neijwiert 尽管类名为base,但这里没有继承。
  • Clang 有助于生成 warning: deleting pointer to incomplete type 'base' may cause undefined behavior [-Wdelete-incomplete]

标签: c++ destructor delete-operator


【解决方案1】:

问题是destruct::destructObj需要查看Base的定义才能知道有一个析构函数可以调用,但它只有一个前向声明。

把你的代码改成这个就可以了。

#include <iostream>
using namespace std;
class base;

class destruct{
    public :
    destruct() {
        cout<<"Destruct Constructor called"<<endl;
    }

    void destructObj(base* obj);

    ~destruct() {
        cout<<"Destruct Destructor called"<<endl;
    }
};

class base {
    int runs;
    public:

    base(){

        cout<<"Constructor called"<<endl;
    }

    ~base(){
        cout<<"destructor called"<<endl;
    }
};

// *** this function after base has been defined ***
inline void destruct::destructObj(base* obj) {
    delete obj;
}

int main() {
    base *obj = new base();
    destruct *desObj = new destruct();
    desObj->destructObj(obj);
    return 0;
}

现在这让我感到惊讶,我想知道它是否是 g++ 扩展。当您尝试 delete 指向只有前向声明的类的指针时,我会预料到编译器错误。但我可能错了。

更新:显然这(删除指向不完整类的指针)是未定义的行为,我猜这意味着它应该编译。但是,您的编译器确实应该给您一个警告,告诉您有问题。始终注意编译器警告,并始终在启用最大可能警告数的情况下进行编译。

【讨论】:

  • 感谢约翰的精彩解释!!。
  • 这是否意味着delete操作释放了obj的内存,但是基类的析构函数因为你说的原因不会执行?
  • @anujbajpai 这显然是你的情况。但是所有 C++ 标准都说行为是未定义的,这意味着任何事情都可能发生。
【解决方案2】:

obj 是一个指向不完整 类型的指针时,您正在调用delete obj。这是未定义的行为(实际上,这通常意味着不调用析构函数,但任何事情都可能发生)。

您需要将base 的定义上移到调用delete 的函数可见的位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 1970-01-01
    • 2017-03-17
    • 2012-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多