C++初始化列表
定義一個類對象時,常常使用初始化列表實例化一個對象,在進入構造函數函數體之前對成員變量完成初始化操作。普通成員變量既可以在初始化中初始化,也可以在函數體重賦值;const成員變量只能在初始化列表中賦值。下面對初始化列表進行一個簡單介紹:
- 使用初始化列表
1 #include <iostream> 2 3 using namespace std; 4 5 class InitTest{ 6 public: 7 InitTest(int x,int y,int z) : a(x),b(y),c(z){} 8 public: 9 void Print() const{ 10 cout<<"a = "<<a<<endl; 11 cout<<"b = "<<b<<endl; 12 cout<<"c = "<<c<<endl; 13 } 14 private: 15 int a; 16 int b; 17 int c; 18 }; 19 20 int main(int argc, char** argv) 21 { 22 InitTest test(10,20,30); 23 test.Print(); 24 25 return 0; 26 }
成員變量被正確賦值,輸出:
- 初始化列表必須使用場景1——const成員變量
1 class InitTest{ 2 public: 3 InitTest(int x,int y,int z){ 4 5 a = x; // error C2758: “InitTest::a”: 必須在構造函數基/成員初始值設定項列表中初始化 6 b = y; 7 c = z; 8 } 9 private: 10 const int a; 11 int b; 12 int c; 13 };
1 class InitTest{ 2 public: 3 InitTest(int x,int y,int z) : a(x){ // OK 4 b = y; 5 c = z; 6 } 7 public: 8 void Print() const{ 9 cout<<"a = "<<a<<endl; 10 cout<<"b = "<<b<<endl; 11 cout<<"c = "<<c<<endl; 12 } 13 private: 14 const int a; 15 int b; 16 int c; 17 };
- 初始化列表必須使用場景2——成員變量或基類未聲明默認構造函數
成員變量未聲明默認構造函數
1 #include <iostream> 2 3 using namespace std; 4 5 class InitTest{ 6 public: 7 InitTest(int x,int y,int z) : a(x),b(y),c(z){} 8 public: 9 void Print() const{ 10 cout<<"a = "<<a<<endl; 11 cout<<"b = "<<b<<endl; 12 cout<<"c = "<<c<<endl; 13 } 14 private: 15 int a; 16 int b; 17 int c; 18 }; 19 20 class HaveInitTest{ 21 InitTest test1; 22 public: 23 HaveInitTest(){} 24 }; 25 26 int main(int argc, char** argv) 27 { 28 HaveInitTest havetest; // error C2512: “InitTest”: 沒有合適的默認構造函數可用 29 30 return 0; 31 }
1 #include <iostream> 2 3 using namespace std; 4 5 class InitTest{ 6 public: 7 InitTest(int x,int y,int z) : a(x),b(y),c(z){} 8 public: 9 void Print() const{ 10 cout<<"a = "<<a<<endl; 11 cout<<"b = "<<b<<endl; 12 cout<<"c = "<<c<<endl; 13 } 14 private: 15 int a; 16 int b; 17 int c; 18 }; 19 20 class HaveInitTest{ 21 InitTest test1; 22 public: 23 HaveInitTest() : test1(0,0,0){} 24 }; 25 26 int main(int argc, char** argv) 27 { 28 HaveInitTest havetest; // OK 29 30 return 0; 31 }
基類未聲明默認構造函數
1 #include <iostream> 2 3 using namespace std; 4 5 class InitTest{ 6 public: 7 InitTest(int x,int y,int z) : a(x),b(y),c(z){} 8 private: 9 int a; 10 int b; 11 int c; 12 }; 13 14 class DerivedFromInitTest : public InitTest{ 15 public: 16 DerivedFromInitTest(){} 17 }; 18 19 int main(int argc, char** argv) 20 { 21 DerivedFromInitTest dervetest; // error C2512: “InitTest”: 沒有合適的默認構造函數可用 22 23 return 0; 24 }
1 #include <iostream> 2 3 using namespace std; 4 5 class InitTest{ 6 public: 7 InitTest(int x,int y,int z) : a(x),b(y),c(z){} 8 private: 9 int a; 10 int b; 11 int c; 12 }; 13 14 class DerivedFromInitTest: public InitTest{ 15 public: 16 DerivedFromInitTest() : InitTest(0,0,0){} 17 }; 18 19 int main(int argc, char** argv) 20 { 21 DerivedFromInitTest derivetest; // OK 22 23 return 0; 24 }
最簡單的解決方法是將InitTest的構造函數聲明為:InitTest(int x = 0,int y = 0,int z = 0)。
- 初始化列表必須使用場景3——聲明為引用類型的成員變量
1 #include <iostream> 2 3 using namespace std; 4 5 class InitTest{ 6 public: 7 InitTest(int &x, int y, int z){ 8 a = x; // error C2758: “InitTest::a”: 必須在構造函數基/成員初始值設定項列表中初始化 9 b = y; 10 c = z; 11 } 12 private: 13 int &a; 14 int b; 15 int c; 16 };
1 class InitTest{ 2 public: 3 InitTest(int &x, int y, int z) : a(x){ // OK 4 b = y; 5 c = z; 6 } 7 private: 8 int &a; 9 int b; 10 int c; 11 };
數據成員初始化順序
數據成員按照他們在類中的聲明順序來初始化,而不是按照在初始化列表中出現的順序。
1 #include <iostream> 2 3 using namespace std; 4 5 class InitTest{ 6 public: 7 InitTest(const int a, const int b) : x(a),y(b){} 11 private: 12 int x; 13 int y; 14 }; 15 16 int main(int argc, char** argv) 17 { 18 InitTest test(10,20); // test.x = 10, test.y = 20 19 20 return 0; 21 }
1 #include <iostream> 2 3 using namespace std; 4 5 class InitTest{ 6 public: 7 InitTest(const int a, const int b) : y(b),x(a + y){} 8 private: 9 int x; 10 int y; 11 }; 12 13 int main(int argc, char** argv) 14 { 15 InitTest test(10,20); // test.x未初始化, test.y = 20 16 17 return 0; 18 }
!總結:初始化列表中,先聲明數據不依賴后聲明數據來初始化。