引子:我們知道,C++中類成員變量的初始化順序與其在類中的聲明順序是有關的。
先看代碼:
1 class TestClass1 2 { 3 public: 4 TestClass1() { 5 cout << "TestClass1()" << endl; 6 } 7 TestClass1(const TestClass1&) { cout << "TestClass1(const TestClass1&)" << endl; } 8 TestClass1& operator=(const TestClass1&) { cout << "TestClas1s& operator=(const TestClass1&)" << endl; return *this; } 9 ~TestClass1() { 10 cout << "~TestClass1()" << endl; 11 } 12 }; 13 14 class TestClass2 15 { 16 public: 17 TestClass2() { 18 cout << "TestClass2()" << endl; 19 } 20 TestClass2(const TestClass2&) { cout << "TestClass2(const TestClass2&)" << endl; } 21 TestClass2& operator=(const TestClass2&) { cout << "TestClass2& operator=(const TestClass2&)" << endl; return *this; } 22 ~TestClass2() { 23 cout << "~TestClass2()" << endl; 24 } 25 }; 26 27 class Test 28 { 29 public: 30 Test() = default; 31 Test(TestClass1& tc1, TestClass2& tc2) :m_tc2(tc2), m_tc1(tc1){} 32 private: 33 TestClass1 m_tc1; 34 TestClass2 m_tc2; 35 };
1 int main() 2 { 3 Test t; 4 }
程序結果為:
現象:先調用TestClass1的構造函數,再調用TestClass2的構造函數。
原因:在類Test中,m_tc1變量聲明在m_tc2變量之前,故m_tc1在m_tc2之前初始化。
問題:在列表初始化的構造函數中,將m_tc2放在m_tc1之前,是否可以讓m_tc2在m_tc1之前初始化?
代碼設計
int main() { TestClass1 tc1; TestClass2 tc2; cout << "/**************************************************************************************/" << endl; Test t(tc1, tc2); }
運行結果為:
可以看到:仍然是TestClass1的構造函數先被調用,TestClass2的構造函數接着被調用。
結論:C++中類成員變量的初始化順序與其在類中的聲明順序是有關的,而與其在初始化列表中的順序無關。
再舉一個例子:
然后我將代碼寫成這樣:
1 class Test 2 { 3 public: 4 Test() = default; 5 Test(TestClass1& tc1, TestClass2& tc2):m_tc2(tc2){} 6 private: 7 TestClass1 m_tc1; 8 TestClass2 m_tc2; 9 }; 10 11 int main() 12 { 13 TestClass1 tc1; 14 TestClass2 tc2; 15 cout << "/**************************************************************************************/" << endl; 16 Test t(tc1, tc2); 17 }
注意與之前代碼的差別:我們在初始化列表中只初始化了m_tc2,沒有動m_tc1。
運行結果:
結果分析:在初始化Test的對象t時,由於m_tc1的聲明順序在m_tc2的聲明順序之前,所以t會想要先初始化m_tc1,但是它在初始化列表中沒有找到初始化m_tc1的內容,於是它只好調用m_tc1的默認構造函數了,完成m_tc1的初始化后,再根據初始化列表中的內容初始化m_tc2。