LiSheng's blog LiSheng's blog
首页
笔记
个人简历
随笔集
GitHub (opens new window)
首页
笔记
个人简历
随笔集
GitHub (opens new window)
  • golang

  • cplus

    • 内存相关

    • 面向对象

      • 相关问题
      • 构造、析构顺序
        • 对象内存布局
        • 静态、动态多态
        • 虚函数表
        • 重载、重写、覆盖
        • 构造函数不能是虚函数
        • CRTP模式的原理和用途
        • 移动语义move
        • 构造函数初始化列表
        • 静态成员变量和函数
        • 多重继承
        • 菱形问题与虚继承
        • 对象池
      • STL相关

      • 内置数据结构
      • 数据结构示例
      • go和c++对比
      • 关键字

    • leetcode

    • 存储技术

    • 分布式系统

    • 计算机网络

    • Linux操作系统

    • Redis

    • 其他

    • 笔记
    • cplus
    • 面向对象
    lisheng
    2024-09-10
    目录

    构造、析构顺序

    在C++中,类对象的初始化和析构顺序是由其继承关系和成员变量的声明顺序决定的。理解这一点对于确保资源的正确管理和避免潜在的内存泄漏至关重要。

    # 一、初始化顺序

    初始化顺序是指对象创建时,构造函数调用的顺序。这个顺序分为以下几部分:

    1. 基类构造函数:在派生类的构造函数执行之前,首先调用基类的构造函数。基类构造函数按照继承层次自上而下依次调用。

    2. 成员对象的构造函数:基类构造函数执行完毕后,按照成员对象在类中声明的顺序依次调用这些成员对象的构造函数。

    3. 派生类构造函数:最后,执行派生类的构造函数。

    # 示例:

    #include <iostream>
    
    class Base {
    public:
        Base() {
            std::cout << "Base Constructor" << std::endl;
        }
        ~Base() {
            std::cout << "Base Destructor" << std::endl;
        }
    };
    
    class Member {
    public:
        Member() {
            std::cout << "Member Constructor" << std::endl;
        }
        ~Member() {
            std::cout << "Member Destructor" << std::endl;
        }
    };
    
    class Derived : public Base {
        Member m;
    public:
        Derived() {
            std::cout << "Derived Constructor" << std::endl;
        }
        ~Derived() {
            std::cout << "Derived Destructor" << std::endl;
        }
    };
    
    int main() {
        Derived d;
        return 0;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37

    输出结果:

    Base Constructor
    Member Constructor
    Derived Constructor
    Derived Destructor
    Member Destructor
    Base Destructor
    
    1
    2
    3
    4
    5
    6

    解释:

    • 首先调用 Base 类的构造函数。
    • 然后按照声明顺序调用 Member 成员对象的构造函数。
    • 最后调用 Derived 类的构造函数。

    # 二、析构顺序

    析构顺序与初始化顺序相反:

    1. 派生类析构函数:首先调用派生类的析构函数。

    2. 成员对象析构函数:然后按照声明顺序的逆序调用成员对象的析构函数。

    3. 基类析构函数:最后调用基类的析构函数。

    在上面的例子中,析构函数的调用顺序是:

    1. Derived 类的析构函数。
    2. Member 成员对象的析构函数。
    3. Base 类的析构函数。

    # 总结

    • 初始化顺序:基类 -> 成员对象 -> 派生类。
    • 析构顺序:派生类 -> 成员对象 -> 基类。

    注意:

    • 成员对象的初始化顺序与它们在类中被声明的顺序一致,而不是在构造函数初始化列表中的顺序。这意味着即使在构造函数中按照不同顺序初始化成员变量,它们也会按照声明顺序进行初始化。
    • 正确理解这些顺序有助于编写健壮的C++代码,避免资源管理中的潜在错误。
    编辑 (opens new window)
    上次更新: 2024/09/13, 11:59:12
    相关问题
    对象内存布局

    ← 相关问题 对象内存布局→

    最近更新
    01
    ceph分布式存储-对象存储(RGW)搭建
    10-27
    02
    ceph分布式存储-集群客户端连接
    10-27
    03
    ceph分布式存储-管理crushmap
    10-27
    更多文章>
    Theme by Vdoing
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式