首页 文章

在C中调用析构函数和构造函数的顺序是什么

提问于
浏览
43

在C中调用析构函数和构造函数的顺序是什么?使用一些基类和派生类的示例

4 回答

  • 10

    The order is:

    • 基础构造函数

    • 派生的构造函数

    • 派生的析构函数

    • 基础析构函数

    Example:

    class B
    {
    public:
      B()
      {  
        cout<<"Construct B"<<endl;
      }
    
      virtual ~B()
      {
        cout<<"Destruct B"<<endl;
      }
    };
    
    class D : public B
    {
    public:
      D()
      {  
        cout<<"Construct D"<<endl;
      }
    
      virtual ~D()
      {
        cout<<"Destruct D"<<endl;
      }
    };
    
    
    
    int main(int argc, char **argv)
    {
      D d; 
      return 0;
    }
    

    Output of example:

    构造B构造D Destruct D Destruct B.

    Multiple levels of inheritance works like a stack:

    如果你考虑将一个项目作为构造推送到堆栈中,并将其作为销毁,那么你可以像堆栈一样查看多个级别的继承 .

    这适用于任何级别 .

    示例D2派生自D派生自B.

    将B推入堆叠,将D推入堆叠,将D2推入堆叠 . 因此施工顺序为B,D,D2 . 然后找出销毁订单开始弹出 . D2,D,B

    More complicated examples:

    有关更复杂的示例,请参阅@JaredPar提供的链接

  • 21

    C FAQ Lite提供了这些事件的详细说明,包括虚拟和多重继承 . 第25.14和25.15节

    https://isocpp.org/wiki/faq/multiple-inheritance#mi-vi-ctor-order

  • 55

    另外,请记住,虽然数组元素是首先构造的 - >最后一个,但它们是按相反的顺序构造的:last - > first .

  • 4

    我必须添加到之前的答案,因为每个人似乎都忽略了它

    derived 类实例为 created 时, base 的构造函数的代码 inside 将被称为 before inside 的构造函数 inside ,但请记住 derived 在技术上仍然是 "created" before base .

    当你有 derived 类析构函数被调用时,派生的析构函数 inside 被称为 before 的代码 inside 基本析构函数是真的,但也要记住 basedestroyed derived derived .

    当我说 created/destroyed 时,我实际上指的是 allocated/deallocated .

    如果查看这些实例的内存布局,您将看到派生实例 composes 基础实例 . 例如:

    内存派生:0x00001110至0x00001120

    基本内存:0x00001114至0x00001118

    因此,派生类必须在构造中分配 BEFORE . 派生类必须在销毁中取消分配 AFTER .

    如果您有以下代码:

    class Base 
    {
    public:
        Base()
        {
            std::cout << "\n  Base created";
        }
        virtual ~Base()
        {
            std::cout << "\n  Base destroyed";
        }
    }
    
    class Derived : public Base 
    {
    public:
        Derived()
        // Derived is allocated here 
        // then Base constructor is called to allocate base and prepare it
        {
            std::cout << "\n  Derived created";
        }
        ~Derived()
        {
            std::cout << "\n  Derived destroyed";
        }   
        // Base destructor is called here
        // then Derived is deallocated
    }
    

    因此,如果您创建了 Derived d; 并且它超出了范围,那么您将在@Brian的答案中获得输出 . 但是内存中的对象行为实际上不是同一个顺序,它更像是这样:

    施工:

    • 派生已分配

    • 已分配基数

    • 基础构造函数被调用

    • 派生的构造函数被调用

    毁灭:

    • 派生的析构函数被调用

    • 基础析构函数调用

    • 基地已取消分配

    • 派生已解除分配

相关问题