构造函数初始化列表 总结 :
在一个类 C 中 , 嵌套了 A 和 B 两个类类型的 对象 作为 成员变量 ;
构造函数的 调用顺序如下 :
析构函数调用顺序 与 构造函数调用顺序相反 , 直接 将 构造函数 调用顺序 倒序排列即可 ;
如果一个类 没有定义 无参构造函数 , 只有一个 有参的构造函数 ,
此时 , C++ 编译器 不会为其 生成 默认的无参构造函数 ;
这种场景下 涉及到了 构造函数 的类型 :
使用如下方式 , 声明 A 和 B 类型的成员变量 , 会自动调用 默认的无参构造函数 初始化对象 , 但是由于 A 和 B 中定义了 有参构造函数 , 无参构造函数 被屏蔽了 ;
A m_a; // A 类型成员变量
B m_b; // B 类型成员变量
没有 无参构造函数 , 上面声明的 A 和 B 两个对象便无法创建成功 ;
此时 , 只能在 构造函数的 初始化列表 中 , 调用 A 和 B 的 有参构造函数 创建 A B 两个成员变量 ;
拷贝构造函数 也是 构造函数 , 也必须在 初始化列表 中 调用 构造函数 , 对子对象进行初始化操作 ;
在下面的代码中 ,
定义了 类 A , 该类实现了 有参构造函数 , 其 无参构造函数 被屏蔽 , 如果要初始化 A 类型的对象 , 必须使用有参构造函数 , 使用 A a
的形式定义的变量 , 无法进行初始化 ;
class A
{
public:
// 带参构造函数
A(int age, int height)
{
m_age = age;
m_height = height;
cout << "执行 A 的构造函数" << endl;
}
~A()
{
cout << "执行 A 的析构函数" << endl;
}
public:
int m_age; // 年龄
int m_height; // 身高
};
定义了 类 B 与 上述 类 A 基本一致 , 也是无法使用 默认的无参构造函数 , 必须调用有参构造函数 ;
定义 类 C , 其中维护了 A 和 B 两个子对象 ,
public:
int m_age; // 年龄
A m_a; // A 类型成员变量
B m_b; // B 类型成员变量
const int m_const_int; // 常量成员
由于 A 和 B 都无法使用 无参构造函数 , 因此在 类 C 的所有构造函数 ( 包括 拷贝构造函数 ) 的 初始化列表中 , 必须强制调用 A 和 B 的 有参构造函数 ;
const int m_const_int
常量成员 , 类 C 的 所有构造函数 ( 包括 拷贝构造函数 ) 的 初始化列表中 , 同时也必须强制对 常量成员进行初始化 ; C() : m_age(10), m_b(5, 110), m_a(10, 150), m_const_int(888)
{}
最终的 构造函数 执行顺序是 :
执行 A 的构造函数
执行 B 的构造函数
执行 C 的构造函数
执行 A 的构造函数
执行 B 的构造函数
执行 C 的 拷贝构造函数
执行
// 通过 C 的有参构造函数
// 其中 构造函数中的参数 作为 参数列表 中的参数值
C c(10, 10, 150, 18, 180);
代码时 , 先后执行 A -> B -> C 类的构造函数 ;
执行
// 调用 C 的拷贝构造函数
C c2 = c;
代码时 , 先执行 A -> B 的构造函数 , 然后执行 C 的拷贝构造函数 ;
#include "iostream"
using namespace std;
class A
{
public:
// 带参构造函数
A(int age, int height)
{
m_age = age;
m_height = height;
cout << "执行 A 的构造函数" << endl;
}
~A()
{
cout << "执行 A 的析构函数" << endl;
}
public:
int m_age; // 年龄
int m_height; // 身高
};
class B
{
public:
// 带参构造函数
B(int age, int height)
{
m_age = age;
m_height = height;
cout << "执行 B 的构造函数" << endl;
}
~B()
{
cout << "执行 B 的析构函数" << endl;
}
public:
int m_age; // 年龄
int m_height; // 身高
};
class C
{
public:
C() : m_age(10), m_b(5, 110), m_a(10, 150), m_const_int(888)
{}
// 构造函数中的参数可以作为 参数列表 中的参数值
C(int age, int ageOfA, int heightOfA, int ageOfB, int heightOfB)
: m_age(age),m_b(ageOfB, heightOfB), m_a(ageOfA, heightOfA), m_const_int(888)
{
cout << "执行 C 的构造函数" << endl;
}
C(const C& c) : m_b(5, 110), m_a(10, 150), m_const_int(888)
{
// 上面的 3 个变量 , 必须在初始化列表中初始化
// m_age 可以在后续进行单独赋值 , 可以不在初始化列表中进行初始化
// 由于 A 和 B 都没有默认构造函数 , 必须在初始化列表中调用 有参构造函数
// m_const_int 成员是常量 , 只能初始化一次 , 不能赋值 ,
// 因此也必须在初始化列表中进行初始化
cout << "执行 C 的 拷贝构造函数" << endl;
}
~C()
{
cout << "执行 C 的析构函数" << endl;
}
public:
int m_age; // 年龄
A m_a; // A 类型成员变量
B m_b; // B 类型成员变量
const int m_const_int; // 常量成员
};
int main()
{
// 通过 C 的有参构造函数
// 其中 构造函数中的参数 作为 参数列表 中的参数值
C c(10, 10, 150, 18, 180);
// 调用 C 的拷贝构造函数
C c2 = c;
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
}
执行结果 :
执行 A 的构造函数
执行 B 的构造函数
执行 C 的构造函数
执行 A 的构造函数
执行 B 的构造函数
执行 C 的 拷贝构造函数
Press any key to continue . . .
执行 C 的析构函数
执行 B 的析构函数
执行 A 的析构函数
执行 C 的析构函数
执行 B 的析构函数
执行 A 的析构函数
D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\Debug\HelloWorld.exe (进程 19692)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .