【C++ Primer 第15章】定义派生类拷贝构造函数、赋值运算符
學(xué)習(xí)資料
? 派生類的賦值運算符/賦值構(gòu)造函數(shù)也必須處理它的基類成員的賦值
??C++ 基類構(gòu)造函數(shù)帶參數(shù)的繼承方式及派生類的初始化
?
定義拷貝構(gòu)造函數(shù)
【注意】對派生類進行拷貝構(gòu)造時,如果想讓基類的成員也同時拷貝,就一定要在派生類拷貝構(gòu)造函數(shù)初始化列表中顯示調(diào)用基類拷貝構(gòu)造函數(shù)(當(dāng)然在函數(shù)體內(nèi)將基類部分的值拷貝也是可以的,只不過它是先用默認(rèn)構(gòu)造函數(shù)初始化后再修改的基類成員變量的值,效率比較低),否則它會調(diào)用基類的默認(rèn)構(gòu)造函數(shù),而不會對基類的成員變量拷貝值,這樣生成的對象,它的派生類部分和被拷貝的對象派生類部分一樣,而基類部分則是默認(rèn)構(gòu)造函數(shù)的初始化結(jié)果。
代碼例子1:
1 #include <iostream> 2 using namespace std; 3 4 class A 5 { 6 public: 7 A() { cout << "A default constructor" << endl; } 8 A(A&) { cout << "A copy constructor" << endl; } 9 }; 10 class B : public A 11 { 12 public: 13 B() { cout << "A default constructor" << endl; } 14 B(B &b) { cout << "B copy constructor" << endl; } 15 }; 16 17 int main() 18 { 19 B b; 20 B c = b; 21 return 0; 22 }輸出結(jié)果:
?
?
代碼例子2:
1 #include <iostream> 2 using namespace std; 3 4 class A 5 { 6 public: 7 A() { cout << "A default constructor" << endl; } 8 A(A&) { cout << "A copy constructor" << endl; } 9 }; 10 class B : public A 11 { 12 public: 13 B() { cout << "A default constructor" << endl; } 14 B(B &b) : A(b) { cout << "B copy constructor" << endl; } 15 }; 16 17 int main() 18 { 19 B b; 20 B c = b; 21 return 0; 22 }輸出結(jié)果:
?
?
C++ 基類構(gòu)造函數(shù)帶參數(shù)的繼承方式及派生類的初始化
在定義類的時候,會遇到基類的構(gòu)造函數(shù)帶參數(shù),而子類子類構(gòu)造函數(shù)不帶參數(shù),這時候如果以代碼 a 的方式建立派生類則會出錯。
1 class A 2 { 3 public: 4 A(int x, int y): i(x), j(y) {} 5 private: 6 int i, j; 7 }; 8 9 class B : public A 10 { 11 public: 12 B() { cout << "init B" << endl; } 13 };在建立B類對象時,編譯出錯:?
?C:\Documents and Settings\admin\桌面\Text1.cpp(104) : error C2512: ‘A’ : no appropriate default constructor available?
?
解決這個問題應(yīng)該在A的構(gòu)造函數(shù)中顯式調(diào)用基類的帶參構(gòu)造函數(shù)。因為在基類中定義了帶參構(gòu)造函數(shù),編譯器不會提供默認(rèn)構(gòu)造函數(shù)。(或者可以在基類中增加一個不帶參數(shù)的構(gòu)造函數(shù))這個問題將解決。?
代碼 b 采用的是調(diào)用基類帶參構(gòu)造函數(shù)的方式:
代碼 b:
1 class A 2 { 3 public: 4 A(int x, int y): i(x), j(y) {} 5 private: 6 int i, j; 7 }; 8 9 class B : public A 10 { 11 public: 12 B() A(10,20) { cout << "init B" << endl; } 13 };?
通過在基類中增加一個不帶參數(shù)的構(gòu)造函數(shù):?
代碼 c:
?
定義派生類賦值運算符
與拷貝和移動構(gòu)造函數(shù)一樣,派生類的賦值運算符也必須為其基類部分賦值。
1 // Base::operator=(const Base&) 不會被自動調(diào)用 2 D& D::operator=(const D &rhs) 3 { 4 Base::operator=(rhs); //為基類部分賦值 5 //按照過去的方式為派生類的成員賦值 6 return *this; 7 }?舉例說明:
1 class base 2 { 3 public: 4 base(int initialvalue = 0): x(initialvalue) {} 5 6 private: 7 int x; 8 }; 9 10 class derived : public base 11 { 12 public: 13 derived(int initialvalue): base(initialvalue), y(initialvalue) {} 14 derived& operator=(const derived& rhs); 15 16 private: 17 int y; 18 }; 19 20 邏輯上說,derived的賦值運算符應(yīng)該象這樣: 21 derived& derived::operator = (const derived& rhs) // 錯誤的賦值運算符 22 { // 請注意d1的base部分沒有被賦值操作改變。 23 if (this == &rhs) 24 return *this; 25 y = rhs.y; 26 return *this; 27 } 28 29 不幸的是,它是錯誤的,因為derived對象的base部分的數(shù)據(jù)成員x在賦值運算符中未受影響。例如,考慮下面的代碼段: 30 31 void assignmenttester() 32 { 33 derived d1(0); // d1.x = 0, d1.y = 0 34 derived d2(1); // d2.x = 1, d2.y = 1 35 36 d1 = d2; // d1.x = 0, d1.y = 1 37 } 38 39 40 derived& derived::operator = (const derived& rhs) // 正確的賦值運算符 41 { 42 if (this == &rhs) 43 return *this; 44 45 base::operator = (rhs); // 調(diào)用this->base::operator= 46 y = rhs.y; 47 48 return *this; 49 }?
轉(zhuǎn)載于:https://www.cnblogs.com/sunbines/p/9215310.html
總結(jié)
以上是生活随笔為你收集整理的【C++ Primer 第15章】定义派生类拷贝构造函数、赋值运算符的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java在注解中绑定方法参数的解决方案
- 下一篇: ES6中新增字符串方法,字符串模板