【C++ Primer 第15章】定义派生类拷贝构造函数、赋值运算符
學習資料
? 派生類的賦值運算符/賦值構造函數也必須處理它的基類成員的賦值
??C++ 基類構造函數帶參數的繼承方式及派生類的初始化
?
定義拷貝構造函數
【注意】對派生類進行拷貝構造時,如果想讓基類的成員也同時拷貝,就一定要在派生類拷貝構造函數初始化列表中顯示調用基類拷貝構造函數(當然在函數體內將基類部分的值拷貝也是可以的,只不過它是先用默認構造函數初始化后再修改的基類成員變量的值,效率比較低),否則它會調用基類的默認構造函數,而不會對基類的成員變量拷貝值,這樣生成的對象,它的派生類部分和被拷貝的對象派生類部分一樣,而基類部分則是默認構造函數的初始化結果。
代碼例子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 }輸出結果:
?
?
代碼例子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 }輸出結果:
?
?
C++ 基類構造函數帶參數的繼承方式及派生類的初始化
在定義類的時候,會遇到基類的構造函數帶參數,而子類子類構造函數不帶參數,這時候如果以代碼 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?
?
解決這個問題應該在A的構造函數中顯式調用基類的帶參構造函數。因為在基類中定義了帶參構造函數,編譯器不會提供默認構造函數。(或者可以在基類中增加一個不帶參數的構造函數)這個問題將解決。?
代碼 b 采用的是調用基類帶參構造函數的方式:
代碼 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 };?
通過在基類中增加一個不帶參數的構造函數:?
代碼 c:
?
定義派生類賦值運算符
與拷貝和移動構造函數一樣,派生類的賦值運算符也必須為其基類部分賦值。
1 // Base::operator=(const Base&) 不會被自動調用 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的賦值運算符應該象這樣: 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部分的數據成員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); // 調用this->base::operator= 46 y = rhs.y; 47 48 return *this; 49 }?
轉載于:https://www.cnblogs.com/sunbines/p/9215310.html
總結
以上是生活随笔為你收集整理的【C++ Primer 第15章】定义派生类拷贝构造函数、赋值运算符的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java在注解中绑定方法参数的解决方案
- 下一篇: ES6中新增字符串方法,字符串模板