1.為什麼要定義虛析構函式?
如果有乙個帶有虛函式功能的類,則它需要乙個虛析構函式,原因如下:
1)如果乙個類有虛函式功能,它經常作為乙個基類使用;
2)如果它是乙個基類,它的派生類經常使用new來分配;
3)如果乙個派生類物件使用new來分配,並且通過乙個指向它的基類的指標來控制,那麼它經常通過乙個指向它的基類的指標來刪除它(如果基類沒有虛析構函式,結果將是不確定的,實際發生時,派生類的析構函式永遠不會被呼叫);
基類有虛析構函式的話,最底層的派生類的析構函式最先被呼叫,然後各個基類的析構函式被呼叫。
2.宣告為保護(protected)的析構函式
如果在乙個派生類中定義了基類以外的成員物件,且基類析構函式不是virtual修飾的,那麼當基類指標或引用指向派生類物件並析構(例如自動物件在函式作用域結束時;或者通過delete)時,會呼叫基類的析構函式而導致派生類定義的成員沒有被析構,產生記憶體洩露等問題。
雖然把析構函式定義成virtual的可以解決這個問題,但是當其它成員函式都不是virtual函式時(即基類中沒有虛函式),會在基類和派生類引入vtable,例項引入vptr造成執行時的效能損失。如果確定不需要直接而是只通過派生類物件使用基類,
可以把析構函式定義為protected(這樣會導致基類和派生類外使用自動物件和delete時的錯誤,因為訪問許可權禁止呼叫析構函式),就不會導致以上問題。
3.建構函式、析構函式宣告為私有和保護時的用法
從語法上來講,乙個函式被宣告為protected或者private,那麼這個函式就不能從「外部」直接被呼叫了。
對於protected的函式,子類的「內部」的其他函式可以呼叫之;
而對於private的函式,只能被本類「內部」的其他函式說呼叫;
通常使用的場景如下:
1)如果你不想讓外面的使用者直接構造乙個類(假設這個類的名字為a)的物件,而希望使用者只能構造這個類a的子類,那你就可以將類a的建構函式/析構函式宣告為protected,而將類a的子類的建構函式/析構函式宣告為public。
例如:class a
public:
....
};calss b : public a
....
};a a; // error
b b; // ok
2)如果將建構函式/析構函式宣告為private,那只能這個類的「內部」的函式才能構造這個類的物件了。
例如:class a
~a()
public:
void instance()//類a的內部的乙個函式
};
上面的**是能通過編譯的。上面**裡的instance函式就是類a的內部的乙個函式。instance函式體裡就構建了乙個a的物件。
但是,這個instance函式還是不能夠被外面呼叫的。為什麼呢?
如果要呼叫instance函式,必須有乙個物件被構造出來。但是建構函式被宣告為private的了。外部不能直接構造乙個物件出來。
a aobj; // 編譯通不過
aobj.instance();
但是,如果instance是乙個static靜態函式的話,就可以不需要通過乙個物件,而可以直接被呼叫。
class a
~a()
public:
static a& instance()
void print()
private:
int data;
};a& ra = a::instance();
ra.print();
上面的**其實是設計模式singleton模式的乙個簡單的c++**實現。
C 虛析構函式 純虛析構函式
虛析構函式 析構函式的工作方式是 最底層的派生類 most derived class 的析構函式最先被呼叫,然後呼叫每乙個基類的析構函式。因為在c 中,當乙個派生類物件通過使用乙個基類指標刪除,而這個基類有乙個非虛的析構函式,則結果是未定義的。執行時比較有代表性的後果是物件的派生部分不會被銷毀。然...
C 虛析構函式 純虛析構函式
虛析構函式 析構函式的工作方式是 最底層的派生類 most derived class 的析構函式最先被呼叫,然後呼叫每乙個基類的析構函式。因為在c 中,當乙個派生類物件通過使用乙個基類指標刪除,而這個基類有乙個非虛的析構函式,則結果是未定義的。執行時比較有代表性的後果是物件的派生部分不會被銷毀。然...
C 虛析構函式 純虛析構函式
虛析構函式 析構函式的工作方式是 最底層的派生類 most derived class 的析構函式最先被呼叫,然後呼叫每乙個基類的析構函式。因為在c 中,當乙個派生類物件通過使用乙個基類指標刪除,而這個基類有乙個非虛的析構函式,則結果是未定義的。執行時比較有代表性的後果是物件的派生部分不會被銷毀。然...