base *pb;
inherit c;//inherit 是繼承 base的
pb=&c;
delete pb;時需要呼叫物件的析構函式,如果基類析構不是virtual型,會根據pb的定義型別呼叫相應類的析構函式,即呼叫即類析構,但如果你在派生類析構裡有記憶體釋放操作,那就會發生記憶體洩漏。假如基類析構是virtual型,會根據pb所指物件的型別呼叫相應類的析構函式,即派生類析構,派生類析構再根據析構函式呼叫的層次原則呼叫即類析構。這樣就保證不會有問題。
effective c++ (第7條:要將多型基類的析構函式宣告為虛函式)
這是因為 c++ 做出了這樣的規定:當乙個派生類物件通過乙個指向基類的指標來刪除,並且這一基類有乙個非虛擬的析構器,此時的結果是不可預知的。通常情況下在執行時,派生類中新派生出的部分得不到銷毀。
如果乙個類不包含虛函式,通常情況下意味著它將不作為基類使用。當乙個類不作為基類時,將它的析構其宣告為虛擬的通常情況下不是個好主意
虛函式的實現需要它所在的物件包含額外的資訊,這一資訊用來在執行時確定本物件需要呼叫哪個虛函式。通常,這一資訊採取乙個指標的形式,這個指標被稱為「 vptr 」(「虛函式表指標」)。 vptr 指向乙個包含函式指標的陣列,這一陣列稱為「 vtbl 」(「虛函式表」),每個包含虛函式的類都有乙個與之相關的 vtbl 。當乙個虛函式被乙個物件呼叫時,就用到了該物件的 vptr 所指向的 vtbl ,在 vtbl 中查詢乙個合適的函式指標,然後呼叫相應的實函式。
需要記住的
應該為多型基類宣告虛析構器。一旦乙個類包含虛函式,它就應該包含乙個虛析構器。
如果乙個類不用作基類或者不需具有多型性,便不應該為它宣告虛析構器。
一點不明白:為什麼基類中析構函式定義為虛函式後,就能執行派生類的析構函式?
我猜測是:因為pb=&c的時候,其派生類的虛函式表指標會複製給基類pb,因此會呼叫其派生類的析構函式,然後再呼叫基類的析構函式。
需要說明的是,當基類的析構函式被宣告為虛函式後,該基類所有的派生類的析構函式不管是否有virtual關鍵字修飾,都將自動宣告為虛函式。
我的理解:有兩種情況是要定義虛析構的
1.如果基類中有虛函式,否則如所說,用基類指標去析構派生類,會析構不完全。
2.如果派生類自定義了operator delete()函式,這時不管基類中是否有沒有虛函式都要虛析構。否則會用你不希望的方式去析構。
虛函式的內部機制
那麼,c++中虛函式為什麼可以實現上述的動態聯編?實際上,虛函式的內部實現機制本身是比較複雜的,且不同的c++編譯器的實現方式又都不一樣的。不過,大多數c++編譯器採用了vtable結構來實現,vtable稱為虛表。
簡單地說,當程式編譯時,編譯就會為虛函式所在的各個類(基類和派生類)各自建立乙個vtable,並將類的虛函式放在此表中,然後在其內部建立乙個指標vptr指向該虛表結構vtable,vptr稱為虛指標。
程式執行時就會根據基類物件所獲取的派生類物件將派生類物件的vtable和vptr複製給基類,並由基類來呼叫,從而實現了類成員函式的動態聯編。
可見,動態聯編時需要指定派生類物件的位址,因而必須通過基類指標或引用物件才能啟用虛函式的動態聯編機制。
需要說明的是:派生類中重寫的虛函式應與基類的虛函式完全一樣,包括虛函式的返回值型別也應一樣。在ansi/iso c++中,對於一般函式來說,函式返回值型別是不能作為一般函式的過載區分內容;但對於虛函式而言,函式返回值型別不同的虛函式被認為兩個不一樣的虛函式。
建構函式,析構函式能否宣告為虛函式
建構函式不能宣告為虛函式 析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式 不建議在建構函式和析構函式裡面呼叫虛函式。建構函式不能宣告為虛函式的原因是 1 構造乙個物件的時候,必須知道物件的實際型別,而虛函式行為是在執行期間確定實際型別的。而在構造乙個物件時,由於物件還未構造成功。編譯器無法知道...
建構函式和析構函式能否宣告為虛函式?
建構函式不能宣告為虛函式,析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式。不建議在建構函式和析構函式裡面呼叫虛函式。建構函式不能宣告為虛函式的原因是 解釋一 所謂虛函式就是多型情況下只執行乙個。而從繼承的概念來講,總是要先構造父類物件,然後才能是子類物件。如果建構函式設為虛函式,那麼當你在構造...
建構函式和析構函式能否宣告為虛函式?
建構函式不能宣告為虛函式,析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式。不建議在建構函式和析構函式裡面呼叫虛函式。建構函式不能宣告為虛函式的原因是 解釋一 所謂虛函式就是多型情況下只執行乙個。而從繼承的概念來講,總是要先構造父類物件,然後才能是子類物件。如果建構函式設為虛函式,那麼當你 在構...