c++ 多態 虛函數 解構函式 抽象類別

來源:互聯網
上載者:User

1. 解構函式和虛解構函式 
    如果基類的解構函式是虛的,那麼它的衍生類別的解構函式都是虛的  
    這將導致:當衍生類別析構的時候,它的所有的基類的解構函式都將得到調用  
    否則,只調用衍生類別的解構函式(這可能導致基類的某些對象沒有得到釋放)     
    所以CObject類的解構函式是虛的,所有由它派生的類析構的時候一級一級的進行,不會造成記憶體流失。

    無論基類的解構函式是否為虛解構函式. 基類的解構函式總是會被自動調用的;但是, 如果用基類指標去操作一個了衍生類別對象,如果不為虛就不能保證衍生類別的解構函式被調用。

2. 純虛解構函式

    解構函式的純虛性唯一效果就是保證抽象類別的執行個體化。

   《Effective C++》中第14條條款的一部分,既是對虛解構函式的徹底理解,亦是對純虛解構函式作用的解釋。

    在某些類裡聲明純虛解構函式很方便。純虛函數將產生抽象類別——不能執行個體化的類(即不能建立此類型的對象)。有些時候,你想使一個類成為抽象類別,但剛好又沒有任何純虛函數。怎麼辦?因為抽象類別是準備被用做基類的,基類必須要有一個虛解構函式,純虛函數會產生抽象類別,所以方法很簡單:在想要成為抽象類別的類裡聲明一個純虛解構函式。

這裡是一個例子:
class awov {
public:
  virtual ~awov() = 0;      // 聲明一個純虛解構函式
};

      這個類有一個純虛函數,所以它是抽象的,而且它有一個虛解構函式,所以不會產生解構函式問題。但這裡還有一件事:必須提供純虛解構函式的定義:

awov::~awov() {}           // 純虛解構函式的定義

這個定義是必需的,因為虛解構函式工作的方式是:最底層的衍生類別的解構函式最先被調用,然後各個基類的解構函式被調用。這就是說,即使是抽象類別,編譯器也要產生對~awov的調用,所以要保證為它提供函數體。如果不這麼做,連結器就會檢測出來,最後還是得回去把它添上。

3. 虛函數  

【1】在基類用virtual聲明成員函數為虛函數。這樣就可以在衍生類別中重新定義此函數,為它賦予新的功能,並能方便地被調用。

【2】在衍生類別中重新定義此函數,要求函數名、函數(返回)類型、函數參數個數和類型與基函數的虛函數相同。如果在衍生類別中沒有對基類的虛函數重定義,則衍生類別簡單地繼承直接基類的虛函數。

【3】C++規定,當一個成員函數被聲明為虛函數後,其衍生類別中的同名函數(符合2中定義的函數)都自動成為虛函數。
【4】定義一個指向基類對象的指標變數,並使其指向同一類族中的某個對象。通過該指標變數調用此函數,此時調用的就是指標變數指向的對象的同名函數。
【5】只能用virtual聲明類的成員函數,使它成為虛函數,而不能將類外的普通函式宣告為虛函數。
【6】一個成員函數被聲明為虛函數後,在同一類族中的類就不能再定義一個非virtual的但與該虛函數具有相同參數(個數與類型)和函數傳回值類型的同名函數。
【7】靜態成員函數不能是虛函數,因為靜態成員函數不受限於某個對象。
【8】inline函數不能是虛函數,因為inline函數是不能在運行中動態確定其位置的。即使虛函數在類的內部定義,編譯時間,仍將其視為非inline的。
【5】使用虛函數,系統要有一定的空間開銷。當一個類帶有虛函數時,編譯器會為該類構造一個虛函數表(virtual function tanle,vtable),它是一個指標數組,存放每個虛函數的入口地址。
4. 純虛函數
 一個函式宣告為純虛後,純虛函數的意思是:我是一個抽象類別!不要把我執行個體化!純虛函數用來規範衍生類別的行為,實際上就是所謂的“介面”。它告訴使用者,我的衍生類別都會有這個函數。
virtual void show()=0;//純虛函數

這裡將show()聲明為純虛函數(pure virtual function)。純虛函數是在聲明虛函數時被“初始化”為0的虛函數。
聲明純虛函數的一般形式為,
virtual 函數類型 函數名(參數列表)=0;

純虛函數沒有函數體;最後的“=0”並不代表函數傳回值為0,它只起形式上的作用,告訴編譯器“這是純虛函數”;這個一個聲明語句,最後有分號。
聲明純虛函數是告訴編譯器,“在這裡聲明了一個虛函數,留待衍生類別中定義”。在衍生類別中對此函數提供了定義後,它才能具備函數的功能,可以被調用。
純虛函數的作用是在基類中為其衍生類別保留了一個函數的名字,以便衍生類別根據需要對它進行定義。
如果在一個類中聲明了純虛函數,而在其衍生類別中沒有對該函數定義,則該函數在衍生類別中仍為純虛函數。

   1. 虛函數和純虛函數可以定義在同一個類(class)中,含有純虛函數的類被稱為抽象類別(abstract class),而只含有虛函數的類(class)不能被稱為抽象類別(abstract class)。
   2. 虛函數可以被直接使用,也可以被子類(sub class)重載以後以多態的形式調用,而純虛函數必須在子類(sub class)中實現該函數才可以使用,因為純虛函數在基類(base class)
只有聲明而沒有定義。

   3. 虛函數和純虛函數都可以在子類(sub class)中被重載,以多態的形式被調用。

   4. 虛函數和純虛函數通常存在於抽象基類(abstract base class -ABC)之中,被繼承的子類重載,目的是提供一個統一的介面。

   5. 虛函數的定義形式:virtual    {method body}
         純虛函數的定義形式:virtual    { } = 0;
         在虛函數和純虛函數的定義中不能有static標識符,原因很簡單,被static修飾的函數在編譯時間候要求前期bind,然而虛函數卻是動態綁定(run-time bind),而且被兩者修飾的函數生命週期(life recycle)也不一樣。
   6. 如果一個類中含有純虛函數,那麼任何試圖對該類進行執行個體化的語句都將導致錯誤的產生,因為抽象基類(ABC)是不能被直接調用的。必須被子類繼承重載以後,根據要求調用其子類的方法。

5  純抽象類別

   從C++的 角度來看,一個抽象類別和一個介面之間沒有任何區別。有時,我們習慣使用“純抽象類別”這個詞來表示某個類僅僅只含有純虛函數(不包含任何資料成員),它是抽象類別的最常見的形式。

   使用純抽象類別有什麼好處?最明顯的例子就是“多介面、單實現”,這是一種很常見的情況。

   在C++中加入了 純虛函數的概念,一個純虛函數必須被其衍生類別重寫。藉助此概念,你可以在一個C++類中通過將其成員函數 聲明為純虛函數的方法表明該類是一個純介面類。從那以後,我就一直強調在C++中,有一種主要的使用類的方法就是讓該類不包含任何狀態, 而僅僅作為一個介面。

6  抽象類別

    將不用來定義對象而只作為一種基本類型用作繼承的類,稱為抽象類別(abstract class),由於它常用作基類,通常稱為抽象基類。凡是包含純虛函數的類都是抽象類別。
    如果在衍生類別中沒有對所有的純虛函數進行定義,則此衍生類別仍然是抽象類別,不能用來定義對象。
可以定義指向抽象類別資料的指標變數。當衍生類別成為具體類後,就可以用這個指標指向衍生類別對象,然後通過該指標調用虛函數。

    帶有純虛函數的類稱為抽象類別。抽象類別是一種特殊的類,它是為了抽象和設計的目的而建立的,它處於繼承階層的較上層。抽象類別是不能定義對象的,在實際中為了強調一個類是抽象類別,可將該類的建構函式說明為保護的存取控制許可權。抽象類別的主要作用是將有關的組織在一個繼承階層中,由它來為它們提供一個公用的根,相關的子類是從這個根派生出來的。抽象類別刻畫了一組子類的操作介面的通用語義,這些語義也傳給子類。一般而言,抽象類別只描述這組子類共同的操作介面,而完整的實現留給子類。抽象類別只能作為基類來使用,其純虛函數的實現由衍生類別給出。如果衍生類別沒有重新定義純虛函數,而衍生類別只是繼承基類的純虛函數,則這個衍生類別仍然還是一個抽象類別。如果衍生類別中給出了基類純虛函數的實現,則該衍生類別就不再是抽象類別了,它是一個可以建立對象的具體類了。

7 java 中的介面   

   不需要聲明介面為抽象或虛擬(本來就是)
   介面不允許有建構函式(純抽象了,根本不需要構造)
   介面不允許有解構函式(本來無構造,何需有析構)
   介面的所有成員都是抽象的(純抽象類別嘛)
   介面只可以從介面繼承(因為只有介面可以保證使純虛的,如果從抽象類別繼承,不能保證抽象類別中可能存在非抽象的成員)
   介面成員不允許有任何修飾(預設就是public的,也只有是public的)
   一個類或結構可以實現多個介面

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.