建構函式不能宣告為虛函式,析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式。
不建議在建構函式和析構函式裡面呼叫虛函式。
建構函式不能宣告為虛函式的原因是:
1 構造乙個物件的時候,必須知道物件的實際型別,而虛函式行為是在執行期間確定實際型別的。而在構造乙個物件時,由於物件還未構造成功。編譯器無法知道物件 的實際型別,是該類本身,還是該類的乙個派生類,或是更深層次的派生類。無法確定。。。
2 虛函式的執行依賴於虛函式表。而虛函式表在建構函式中進行初始化工作,即初始化vptr,讓他指向正確的虛函式表。而在構造物件期間,虛函式表還沒有被初 始化,將無法進行。
虛函式的意思就是開啟動態繫結,程式會根據物件的動態型別來選擇要呼叫的方法。然而在建構函式執行的時候,這個物件的動態型別還不完整,沒有辦法確定它到底是什麼型別,故建構函式不能動態繫結。(動態繫結是根據物件的動態型別而不是函式名,在呼叫建構函式之前,這個物件根本就不存在,它怎麼動態繫結?)
編譯器在呼叫基類的建構函式的時候並不知道你要構造的是乙個基類的物件還是乙個派生類的物件。
析構函式設為虛函式的作用:
解釋:在類的繼承中,如果有基類指標指向派生類,那麼用基類指標delete時,如果不定義成虛函式,派生類中派生的那部分無法析構。
例:#include "stdafx.h"
#include "stdio.h"
class a
;a::a()
a::~a()
class b : public a
;b::b()
b::~b()
int main(int argc, char* argv)
輸出結果為:delete class b
delete class a
如果把a的virtual去掉:那就變成了delete class a
也就是說不會刪除派生類裡的剩餘部分內容,也即不呼叫派生類的虛函式
因此在類的繼承體系中,基類的析構函式不宣告為虛函式容易造成記憶體洩漏。所以如果你設計一定類可能是基類的話,必須要宣告其為虛函式。正如
symbian
中的cbase
一樣。
note:
1. 如果我們定義了乙個建構函式,編譯器就不會再為我們生成預設建構函式了。
2. 編譯器生成的析構函式是非虛的,除非是乙個子類,其父類有個虛析構,此時的函式虛特性來自父類。
3. 有虛函式的類,幾乎可以確定要有個虛析構函式。
4. 如果乙個類不可能是基類就不要申明析構函式為虛函式,虛函式是要耗費空間的。
5. 析構函式的異常退出會導致析構不完全,從而有記憶體洩露。最好是提供乙個管理類,在管理類中提供乙個方法來析構,呼叫者再根據這個方法的結果決定下一步的操作。
6. 在建構函式不要呼叫虛函式。在基類構造的時候,虛函式是非虛,不會走到派生類中,既是採用的靜態繫結。顯然的是:當我們構造乙個子類的物件時,先呼叫基類的建構函式,構造子類中基類部分,子類還沒有構造,還沒有初始化,如果在基類的構造中呼叫虛函式,如果可以的話就是呼叫乙個還沒有被初始化的物件,那是很危險的,所以c++中是不可以在構造父類物件部分的時候呼叫子類的虛函式實現。但是不是說你不可以那麼寫程式,你這麼寫,編譯器也不會報錯。只是你如果這麼寫的話編譯器不會給你呼叫子類的實現,而是還是呼叫基類的實現。
7.
在
析構函式中
也不要呼叫虛函式。在析構的時候會首先呼叫子類的析構函式,析構掉物件中的子類部分,然後在呼叫基類的析構函式析構基類部分,如果在基類的析構函式裡面呼叫虛函式,會導致其呼叫已經析構了的子類物件裡面的函式,這是非常危險的。
8. 記得在寫派生類的拷貝函式時,呼叫基類的拷貝函式拷貝基類的部分,不能忘記了。
建構函式不能宣告為虛函式
建構函式不能宣告為虛函式的原因 1.所謂虛函式就是多型情況下只執行乙個,而從繼承的概念來講,總是先構造父類物件,然後才能使子類物件,如果建構函式設為虛函式,那麼你在構造父類的建構函式時就不得不顯式的呼叫構造,還有乙個原因就是為了防錯誤的發生,試想如果你在子類中一不小心重寫了個跟父類建構函式一樣的函式...
為什麼建構函式不能宣告為虛函式,析構函式可以
建構函式不能宣告為虛函式,析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式。不建議在建構函式和析構函式裡面呼叫虛函式。建構函式不能宣告為虛函式的原因是 1 構造乙個物件的時候,必須知道物件的實際型別,而虛函式行為是在執行期間確定實際型別的。而在構造乙個物件時,由於物件還未構造成功。編譯器無法知道...
為什麼建構函式不能宣告為虛函式,析構函式可以
建構函式不能宣告為虛函式,析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式。不建議在建構函式和析構函式裡面呼叫虛函式。建構函式不能宣告為虛函式的原因是 1 構造乙個物件的時候,必須知道物件的實際型別,而虛函式行為是在執行期間確定實際型別的。而在構造乙個物件時,由於物件還未構造成功。編譯器無法知道...