15.4.3 復制控制和繼承
派生類也可以使用合成復制控制成員。合成操作對對象的基類部分連同派生部分的成員一起進行復制、賦值或撤銷,使用基類的復制構造函數、賦值操作符或析構函數對基類部分進行復制、賦值或撤銷。
只包含類類型或內置類型數據成員、不含指針的類一般可以使用合成操作,復制、賦值或撤銷這樣的成員不需要特殊控制。具有指針成員的類一般需要定義自己的復制控制來管理這些成員。
1. 定義派生類復制構造函數
如果派生類顯式定義自己的復制構造函數或賦值操作符,則該定義將完全覆蓋默認行為。被繼承類的復制構造函數和賦值操作符負責對基類成分以及類自己的成員進行復制或賦值。
#include "stdafx.h"
#include <iostream>
using namespace std;
class Base
{
protected:
int value1, value2;
protected:
Base(int val1, int val2)
{
value1=val1;
value2=val2;
}
Base(const Base &b)
{
value1=b.value1;
value2=b.value2;
}
};
class Child:Base
{
private:
int value3;
public:
Child(int val1,int val2,int val3):value3(val3),Base(val1,val2){}
Child(const Child &c):value3(c.value3), Base(c){}
};
2. 派生類賦值操作符
如果派生類定義了自己的賦值操作符,則該操作符必須對基類部分進行顯式賦值。
Child &operator= (const Child &c)
{
if(this!=&c)
{
Base::operator=(c);
value3=c.value3;
}
return *this;
}
賦值操作符必須防止自身賦值,假定左右操作數不同,則調用Base類的賦值操作符給基類部分賦值。該操作符可以由類定義,也可以是合成賦值操作符,這沒什麼關系——我們可以直接調用它。基類操作符將釋放左操作數中基類部分的值,並賦以來自c的新值。該操作符執行完畢後,接著要做的是為派生類中的成員賦值。
3. 派生類析構函數
析構函數的工作與復制構造函數和賦值操作符不同:派生類析構函數不負責撤銷基類對象的成員。編譯器總是顯式調用派生類對象基類部分的析構函數。每個析構函數只負責清除自己的成員。
對象的撤銷順序與構造順序相反:首先運行派生類析構函數,然後按繼承層次依次向上調用各基類析構函數。
摘自 xufei96的專欄