(1)如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,没有默认构造函数。这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么它将无法完成第一步,就会报错。

#include <iostream>

using namespace std;

class A {
private:
int m_a;

public:
A(int a) {
cout << "A()..." << endl;
m_a = a;
}

~A() {
cout << "A被析构了" << endl;
}

void printA() {
cout << "a = " << m_a << endl;
}

};

class B {
private:
int m_b;
A m_a1;
A m_a2;

public:
B(A &a1, A &a2, int b) : m_a1(a1), m_a2(a2) { // 初始化列表
cout << "B(A&, A&, int)....." << endl;
m_b = b;
}

~B() {
cout << "B被析构了" << endl;
}

void printB() {
cout << "b = " << m_b << endl;
m_a1.printA();
m_a2.printA();
}
};

int main(){
A a1(10), a2(100);

B b(a1, a2, 1);

b.printB();
}
#include <iostream>

using namespace std;

class A {
public:
//显示提供一个带参数的构造函数
A(int a) {
m_a = a;
cout << "a = " << m_a << "调用了构造函数" << endl;

}
~A(){
cout << "a = " << m_a << "被析构了" << endl;
}

void printA(){
cout << " a = " << m_a << endl;
}
private:
int m_a;
};

class B {
public:
B(A& a1, A& a2, int b) : m_a1(a1), m_a2(a2) { // 初始化列表
cout << "B(A&, A&, int)....." << endl;
m_b = b;
}

B(int a1, int a2, int b) : m_a1(a1), m_a2(a2) {
cout << "B(int, int, int)" << endl;

m_b = b;
}

void printB() {
cout << "b = " << m_b << endl;
m_a1.printA();
m_a2.printA();
}

~B() {
cout << "b = " << m_b << " 调用了析构函数" << endl;
}

private:
int m_b;
A m_a2;
A m_a1;
};

int main(void) {

B b2(30, 40, 50);
b2.printB();

return 0;
}

注:

  1. 类内部的对象初始化的顺序,跟对象的定义顺序一样,跟初始化列表中的顺序无关
  2. 析构的顺序就跟构造的顺序相反

(2)当类成员中含有一个const对象时,或者是一个引用时,他们也必须要通过成员初始化列表进行初始化,因为这两种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。初始化列表中的初始化顺序,与声明顺序有关,与前后赋值顺序无关。

#include <iostream>

using namespace std;

class A{
public:
//显示提供一个带参数的构造函数
A(int a){
m_a = a;
cout << "a = " << m_a << "调用了构造函数" << endl;

}

~A(){
cout << "a = " << m_a << "被析构了" << endl;
}

void printA(){
cout << " a = " << m_a << endl;
}
private:
int m_a;
};

class B{
public:
B(int b) :a1(10), a2(100) { //在初始化B的时候通过初始化列表给内部对象a1 和a2 进行了初始化

m_b = b;
/*
a1(10);
a2(20);
*/
cout << "b = " << m_b << "调用了构造函数" << endl;
}

B(int aa1, int aa2, int b) : a1(aa1), a2(aa2), m_b(b) { //通过初始化列表不仅能够初始化成员对象, 还可以初始化成员变量

}

void printB(){
cout << "b = " << m_b << endl;
a1.printA();
a2.printA();
}

~B(){
cout << "b = " << m_b << " 调用了析构函数" << endl;
}

private:
int m_b;
A a2;
A a1;
};

//类内部的对象初始化的顺序,跟对象的定义顺序一样,跟初始化列表中的顺序无关
//析构的顺序就跟构造的顺序相反

class ABC{
public:

ABC(int a, int b, int c, int m) :m_m(m) { // const常量只能在 初始化列表中 初始化
cout << "ABC(int, int, int)" << endl;
m_a = a;
m_b = b;
m_c = c;
// const 常量不能在这里进行初始化操作
}


~ABC(){
cout << "~ABC()" << endl;
}

void printABC(){
cout << m_a << "," << m_b << "," << m_c << "," << endl;
}

private:
int m_a;
int m_b;
int m_c;
const int m_m; // 常量
};


class ABCD{
public:
ABCD(int a, int b, int c, int d, int m) :m_abc(a, b, c, m), m_d(d) {//常量成员变量不能够赋值,只能通过初始化列表进行初始化

m_d = d;
}

ABCD(ABC&abc, int d) :m_abc(abc){
m_d = d;
}

private:
ABC m_abc;
int m_d;
};

int main(void){

B b(10, 20, 30);

b.printB();

ABC abc(10, 20, 30, 6);
ABCD abcd(1, 2, 3, 4, 6);

ABCD abcd1(abc, 40);

}

注:通过初始化列表不仅能够初始化成员对象, 还可以初始化成员变量。