【问题标题】:Inner class destructor is called after Base class destructor在基类析构函数之后调用内部类析构函数
【发布时间】:2016-04-27 15:55:17
【问题描述】:

我有一个基本而简单的问题。

我有这种情况:

#include <iostream>
using namespace std;

class Inner1
{
public:
    ~Inner1() {cout << "Inner1 Des\n";};
};

class Inner2
{
public:
    ~Inner2() {cout << "Inner2 Des\n";};
};

class Base
{
public:
    ~Base() {cout << "Base Des\n";};

    Inner1 inner1;
    Inner2 inner2;
};

int main() {
    Base base;
    return 0;
}

我的控制台现在告诉我:

调用基础析构函数
调用 Inner2 析构函数
调用了 Inner1 析构函数

这是正常行为吗?因为某些功能的功能
在我的基类析构函数中已经被销毁,内部类依赖 在他们身上。

不推荐的解决方法:

只需在第一个位置添加一个带有对象的“Destroyer”类:

[...]
class Base
    {
    public:
        ~Base() {cout << "Base Des\n";};

        class Destroyer
        {
             ~Destroyer()
             {
                 //Put the stuff here because this destr will be called last
                 cout << "Destroyer Des\n";
             }
        } _destroyer;
        Inner1 inner1;
[...]

感谢您的帮助

【问题讨论】:

  • 您应该向我们展示生成这些消息的代码。否则我们只是在猜测行为。
  • 那不是子类而是内部类。子类化是指继承。 那么派生类的dtors会在基类析构函数之前被调用。
  • 这些消息只是我添加到每个析构函数中的标准 cout 消息,没什么特别的。它只是关于这种情况和标准 c++ 我认为它与我的其他代码无关。
  • 请提供MCVE代码
  • @Albjenow 这说这对于内部类来说是正常的?

标签: c++ c++11 destructor


【解决方案1】:

这是正常行为吗?

是的。子对象析构函数由容器类的析构函数调用。特别是,子对象将在容器类析构函数的主体被执行后被销毁。

因为某些功能的功能 在我的基类析构函数中已经被销毁,内部类依赖它们。

只有当内部类 [原文如此] 析构函数依赖于包含它们的 Base 实例时,这才是一个问题。在这种情况下,Base 不应将它们包含为成员,或者它们的析构函数不应依赖于 Base

【讨论】:

    【解决方案2】:

    使用此代码:

    #include <iostream>
    
    class Base
    {
        public:
            class Sub1
            {
                public:
                    Sub1()
                    {
                        std::cout << "Base::Sub1::Constructed\n";
                    }
                    ~Sub1()
                    {
                        std::cout << "Base::Sub1::Destroyed\n";
                    }
            };
            class Sub2
            {
                public:
                    Sub2()
                    {
                        std::cout << "Base::Sub2::Constructed\n";
                    }
                    ~Sub2()
                    {
                        std::cout << "Base::Sub2::Destroyed\n";
                    }
            };
    
    
            Sub1    sub1;
            Sub2    sub2;
            Base()
            {
                std::cout << "Base::Constructed\n";
            }
            ~Base()
            {
                std::cout << "Base::Destroyed\n";
            }
    };
    
    int main()
    {
        Base    base;
    }
    

    我得到(手动添加 cmets)

    > ./a.out
    // Build all members first in the order they are declared.
    Base::Sub1::Constructed
    Base::Sub2::Constructed
    // Call the constructor of the object
    Base::Constructed
    
    // Destruction happens in revers.
    // Calls the destructor code to handle all local resources
    Base::Destroyed
    // Then destroy all members in reverse order of declaration
    Base::Sub2::Destroyed
    Base::Sub1::Destroyed
    

    【讨论】:

    • 是的,这就是我的问题。您能给我一些建议如何处理这种情况吗?
    • @Coda:有什么问题。这就是 C++ 的定义方式。
    • 我知道,但是我应该怎么做“因为某些函数的功能已经在我的基类析构函数中被破坏了,而内部类依赖于它们。”。
    • 将功能形式 SubX::~SubX 移动到某个函数,例如在 Base::~Base 中调用的 SubX::cleanUp
    • inner classes 请使用正确的术语members。你将不得不改变你的设计(你不能改变这种行为)。但您目前的描述过于模糊,无法提供任何具体建议。
    【解决方案3】:

    类成员按照它们在类中定义的顺序构造。也就是说,

    class Demonstration
    {
        XClass x;
        YClass y;
    };
    

    在上面的例子中,x 将在y 之前构造。由于破坏以相反的构造顺序发生,y 将始终在 x 之前被破坏。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-08
      • 1970-01-01
      • 1970-01-01
      • 2011-04-28
      • 2014-09-18
      • 2018-01-02
      • 1970-01-01
      • 2015-07-18
      相关资源
      最近更新 更多