C++中类的构造函数调用顺序为:

  1. 如果类中有静态成员变量,先实例化静态变量。
  2. 如果类是继承类,先调用基类的构造函数再初始化当前对象。
  3. 执行构造函数初始化列表对初始化列表中的变量进行初始化。
  4. 初始化各个成员变量,使用默认初始化或者默认值初始化。
  5. 执行构造函数内的初始化,初始化完毕。
#include<iostream>
using namespace std;

class A{
public:
    A() {
        cout << "A()" << endl;
    }
    A(int i){
        cout << "A(" << i << ")" << endl;
    }
};

class B: public A{
public:
    A m_a2;
    A m_a1 = -1;
    A m_a3 = -3;
    A m_a4;
    static A m_sa;
    B(): A(99), m_a1(1), m_a2(2) {
        m_a4 = 6;
    };
};

A B::m_sa(100);

int main(){
    B b;
    return 0;
}

结果输出为:

A(100) // 静态变量m_sa
A(99)  // 基类初始化
A(2)  // m_a2初始化
A(1)  // m_a1初始化
A(-3)  // m_a3初始化
A()  // m_a4初始化
A(6)  // 构造函数内对m_a4重新赋值

注意事项

  • 执行初始化列表时,初始化顺序为成员变量的定义顺序而不是列表中的顺序。所以上面先对m_a2进行了初始化然后再会m_a1初始化。
  • m_a4进行了两次初始化是因为在执行完列表初始化后对该变量进行默认初始化,然后再次在构造函数中重新赋值初始化。
  • 静态成员变量必须在类外显示初始化,初始化格式为:type class-name::static-var = value;,初始化时不考虑变量的共有和私有属性。

其他

对于一些编译器,在编译以上代码时可能会有警告:

field ''m_a1'' will be initialized after field ''m_a2''

因为m_a1定义晚于m_a2但是在初始化列表中的顺序比m_a2前,可能会造成意想不到的结果。

class C {
public:
    int m_j;
    int m_i;
    C(int i): m_j(m_i), m_i(i){
    } 
};

int main(){
    C c(99);
    cout << c.m_i << " " << c.m_j << endl;
    return 0;
}

实际结果为99 0,因为m_j的定义早于m_i,在初始化列表中也先使用m_j(m_i)初始化,此时m_i0

最后修改:2018 年 12 月 16 日
如果觉得我的文章对你有用,请随意赞赏