【问题标题】:Destructors not called未调用的析构函数
【发布时间】:2013-09-19 12:35:33
【问题描述】:

为什么不调用析构函数?

尽管我已经为 A 类和 B 类编写了析构函数,但它并没有被调用。


#include<iostream.h>
#include<conio.h>

class A {
    public :

    A() {
        cout<<"\nIn A const.";
    }

    ~A() {
        cout<<"\nIn A dest.";
    }
};

class B : public A {
    public :

    B() {
        cout<<"\nIn B const.";
    }

    ~B() {
        cout<<"\nIn B dest.";
    }
};

int main() {
    A a;
    B b;
    getch();
    return 0;
}

为什么不调用构造函数?

【问题讨论】:

  • Cannot reproduce。为什么你认为他们没有被召唤?
  • 因为你的编译器完全坏了?或者您正在运行与此代码不对应的可执行文件?你能发布一些重现问题的真实代码吗?
  • 在不相关的注释上,更喜欢将新行粘贴在行尾(您甚至可以使用cout &lt;&lt; "My Text" &lt;&lt; endl;)。这在程序执行后不会自动插入新行的终端中效果更好。回到问题:你使用的是什么编译器,我假设你已经包含了&lt;iostream&gt;

标签: c++ class object destructor


【解决方案1】:

一旦退出包含对象的块,就会执行分配在堆栈上的对象的析构函数。

如果稍加修改,您的代码将显示在 getch() 之前调用的析构函数

int main() {
    {
        A a;
        B b;
    }
    getch();
    return 0;
}

这里我使用了一对额外的大括号来定义一个内部块。该块内定义的对象将在该块退出时被销毁(因此在等待键盘输入之前)。

在您的代码中,当退出 main 主体块时调用析构函数,这意味着在等待键盘之后。

【讨论】:

  • 我刚才试过了,从来没有调用析构函数。
  • @James:肯定会调用析构函数。可能您没有看到输出,因为终端是行缓冲的。在每个输出后添加换行符,您将看到在此代码中,构造函数和析构函数都在等待getch() 中的字符之前执行。
  • 实际上,我知道发生了什么。首先,当证明它们没有被调用时,我将文件写入放入析构函数中。我做了更多的研究,发现我实际上应该使用标准指针来传递函数并维护对父/子类的引用。一旦我这样做了,析构函数就开始被调用。
【解决方案2】:

g++ 4.6没有问题

 mahmood@la:~$ g++ -o test test.cpp
 mahmood@la:~$ ./test

 In A const.
 In A const.
 In B const.
 In B dest.
 In A dest.
 In A dest.mahmood@la:~$ 

【讨论】:

    【解决方案3】:
    class A {
    public :
    
    A() {
        cout<<"\nIn A const.";
    }
    
    virtual ~A() {
        cout<<"\nIn A dest.";
    }
    };
    

    解构函数应该是virtual

    【讨论】:

    • 这会有什么不同?
    • 这可能会导致内存链接。
    • 这仅在将 B* 分配给 A* 类型的左值时才有意义。在这种情况下,如果尝试使用非虚拟析构函数将该值作为 A* 删除,则将调用 A 的析构函数,而不是 B 的析构函数,而如果析构函数是虚拟的,则将调用 B 的析构函数(之后也是 A)。
    猜你喜欢
    • 2023-04-08
    • 2017-04-28
    • 2013-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 2011-04-16
    相关资源
    最近更新 更多