c 構造 析構 賦值 運算

2022-08-10 17:21:13 字數 2612 閱讀 5160

1 為多型基類宣告virtual析構函式

帶有多型形態的base classs應該宣告乙個virtual析構函式。如果該class帶有任何virtual的函式,它就應該擁有乙個virtual析構函式。這樣用基類指標指向的派生類的析構的時候,才會呼叫到自己的析構函式,將派生類的所有部分都析構掉,否則只會析構掉基類的部分,造成析構不完全、記憶體洩漏等問題。當建立乙個純虛的析構函式時,你必須為其提供乙個定義,否則在鏈結的時候會出錯。析構函式的運作方式是:最深層的派生(most derived)的那個class其析構函式最先被呼叫,然後是每乙個base class的析構函式被呼叫。編譯器會在awov的derived classes的析構函式中建立乙個對~awov的呼叫動作。所以你必須為~awov提供乙個定義。

class awov

public:

virtual ~awov() = 0;  // pure virtual析構函式

awov:~awov(){}    // pure virtual析構函式的定義

classes的設計目的如果不是作為base classes使用的、或者不是為了具備多型性的,就不該宣告virtual析構函式。如果乙個class內含virtual函式,其物件的體積會變大,因為在物件模型的開始位置多了乙個指向虛函式表(vptl)的虛函式指標(vptr)。stl容器中的string, vector, list, set, tr1::unordered_map等類都是沒有帶有virtual析構函式的,它們也不適用於當基類。

2 建構函式和析構函式的異常

建構函式可以丟擲異常,然後會觸發對構造出來的部分進行析構(也只有當建構函式丟擲異常的時候會觸發對應的析構),c++對此是保證的。

析構函式不能丟擲異常,要在內部就對他進行捕獲或者進行處理

析構函式絕對不要提出異常。如果乙個被析構的函式呼叫的函式可能丟擲異常,析構函式應該捕捉任何異常,然後吞下他們(不傳播)或者結束程式。

如果客戶需要對某個操作函式執行期間丟擲的異常作出反應,那麼class應該提供乙個普通函式(而非在析構函式中)執行該操作。

3 絕不在構造和析構過程中呼叫virtual函式

在建構函式的過程中,base class建構函式的執行更早於derived建構函式,當base class建構函式執行時derived class的成員變數尚未初始化,若此期間呼叫的virtual函式是derived class的函式,則其有可能用到了derived class中那些尚未初始化的成員變數,會導致未定義的行為。實際上,上述並不會發生。因為在derived class物件的base class的構造期間,物件的型別是base class而不是derived class。不只virtual 函式會被編譯器解析至base class ,若使用執行期間型別資訊(runtime type infomation, 例如dynamic_cast和typeid),也會把物件視為base class型別。所以呼叫到virtual 函式的只會是base class層面的函式。如果在base class層面該virtual函式沒有被定義(純虛函式),則會導致鏈結錯誤;否則,呼叫到的函式並不是我們希望的derived class層面的virtual 函式。

相同道理也可適用於析構函式。一旦derived class析構函式開始執行時,物件內derived class成員變數便呈現未定義值。進入derived class 的析構函式時,它就被當成是base class。

4 令operator= 返回乙個reference to *this

class widget

};這樣就可以方便於寫成賦值的連鎖方式:

int x, y, z;

x = y = z = 20;

這個協議也適用於所有賦值相關的運算, 例如+=, -=, *=

5 複製物件時勿忘其每乙個部分

copying 函式應該確保複製「物件內的所有成員變數」及「所有base classes成分」

不要嘗試以某個copying 函式實現另乙個copying函式。應該將其共同機能放進第三個函式中,並由兩個copying函式共同呼叫。

class base

public:

base(const base& rhs) : name(rhs.name){}

base& operator=(const base& rhs)

name = rhs.name;

private:

std::string name;  

class derived : public base

public:

derived(const derived& rhs) : base(rhs), derivednum(rhs.derivednum) {}

derived& operator=(const derived& rhs)

base::operator=(rhs);

derivednum = rhs.derivednum;

private:

int derivednum;

C 構造 析構 賦值運算

有時候,某個物件是獨一無二的,不能沒複製也不能被賦值!所以我們要強制編譯器不允許使用 和copy 建構函式,但如果你不寫他們,編譯器又會自動幫你加上,問題由此引發。class home uncopyable private uncopyable const uncopyable uncopyable...

構造 析構 賦值運算

非內建資料型別 一般而言,只有當生出的 合法且有適當機會證明它有意義,編譯器才會為class 生出operator 建構函式 析構函式 stl 或標準庫或已經存在的,不包含虛函式的類,我們不應該繼承它們 比較好的一種辦法是,自己在析構函式中,可以選擇,記錄並退出,或者記錄並繼續執行。但同時提供乙個p...

構造 析構 賦值運算

條款05 了解c 默默編寫並呼叫哪些函式 如果我們寫了乙個空類 class empty 編譯器會為這個類新增一些default的函式,相當於 class empty default建構函式 empty const empty rhs copy建構函式 empty 析構函式 empty operato...