**<>
建構函式不能宣告為虛函式,析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式。
不建議在建構函式和析構函式裡面呼叫虛函式。
建構函式不能宣告為虛函式的原因是:
解釋一:所謂虛函式就是多型情況下只執行乙個。而從繼承的概念來講,總是要先構造父類物件,然後才能是子類物件。如果建構函式設為虛函式,那麼當你 在構造父類的建構函式時就不得不顯示的呼叫構造。還有乙個原因就是為了防錯,試想如果你在子類中一不小心重寫了個跟父類建構函式一樣的函式,那麼你的父類 的建構函式將被覆蓋,也即不能完成父類的構造.就會出錯。
解釋二:虛函式的主要意義在於被派生類繼承從而產生多型。派生類的建構函式中,編譯器會加入構造基類的**,如果基類的建構函式用到引數,則派生類在其建構函式的初始化列表中必須為基類給出引數,就是這個原因。
虛函式的意思就是開啟動態繫結,程式會根據物件的動態型別來選擇要呼叫的方法。然而在建構函式執行的時候,這個物件的動態型別還不完整,沒有辦法確 定它到底是什麼型別,故建構函式不能動態繫結。(動態繫結是根據物件的動態型別而不是函式名,在呼叫建構函式之前,這個物件根本就不存在,它怎麼動態綁 定?)
編譯器在呼叫基類的建構函式的時候並不知道你要構造的是乙個基類的物件還是乙個派生類的物件。
析構函式設為虛函式的作用:
解釋:在類的繼承中,如果有基類指標指向派生類,那麼用基類指標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. 記得在寫派生類的拷貝函式時,呼叫基類的拷貝函式拷貝基類的部分,不能忘記了。
如果乙個類是作為基類使用,那麼他的虛構函式一定要是虛的,即用virtual關鍵字(引數為零則為純虛函式).
否則會有記憶體洩漏(很重要),因為當用基類的指標刪除乙個派生類的物件時,要呼叫派生類的析構函式.但是
其子類或者子子類可以的析構函式可以是虛函式,也可以不是虛函式.(不加virtual 關鍵字則不會呼叫派生
類的析構函式,而上面用了clxbase *ptest = new clxderived;語句也就是new的clxderived物件沒有 銷毀,所以產生記憶體洩漏)
2.類中的虛函式,如果乙個類中的函式被宣告成為虛函式,那麼其子類不用在宣告為虛函式(當子類還有子類時),
也可以宣告為虛函式.結果是一樣的.同虛析構函式的道理是一樣的.當然,並不是要把所有類的析構函式都寫
成虛函式。因為當類裡面有虛函式的時候,編譯器會給類新增乙個虛函式表,裡面來存放虛函式指標,這樣就
會增加類的儲存空間。所以,只有當乙個類被用來作為基類的時候,才把析構函式寫成虛函式。
具體例子:
#include "iostream.h"
class clxbase
; virtual ~clxbase() ;
virtual void dosomething() ;
};class clxderived : public clxbase
; virtual~clxderived() ;
//此處的virtual可以去掉
virtual void dosomething() ;
//此處的virtual可以去掉
};class clxthrived : public clxderived
; virtual ~clxthrived();
//此處的virtual可以去掉
virtual void dosomething()
//此處的virtual可以去掉
};void main()
建構函式,析構函式能否宣告為虛函式
建構函式不能宣告為虛函式 析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式 不建議在建構函式和析構函式裡面呼叫虛函式。建構函式不能宣告為虛函式的原因是 1 構造乙個物件的時候,必須知道物件的實際型別,而虛函式行為是在執行期間確定實際型別的。而在構造乙個物件時,由於物件還未構造成功。編譯器無法知道...
建構函式和析構函式能否宣告為虛函式?
建構函式不能宣告為虛函式,析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式。不建議在建構函式和析構函式裡面呼叫虛函式。建構函式不能宣告為虛函式的原因是 解釋一 所謂虛函式就是多型情況下只執行乙個。而從繼承的概念來講,總是要先構造父類物件,然後才能是子類物件。如果建構函式設為虛函式,那麼當你在構造...
析構函式宣告為虛函式
base pb inherit c inherit 是繼承 base的 pb c delete pb 時需要呼叫物件的析構函式,如果基類析構不是virtual型,會根據pb的定義型別呼叫相應類的析構函式,即呼叫即類析構,但如果你在派生類析構裡有記憶體釋放操作,那就會發生記憶體洩漏。假如基類析構是vi...