C++:抽象基類和純虛函數的理解


 轉載地址:http://blog.csdn.net/acs713/article/details/7352440

抽象類是一種特殊的類,它是為了抽象和設計的目的為建立的,它處於繼承層次結構的較上層。

      ⑴抽象類的定義:

      稱帶有純虛函數的類為抽象類。

      ⑵抽象類的作用:

      抽象類的主要作用是將有關的操作作為結果接口組織在一個繼承層次結構中,由它來為派生類提供一個公共的根,派生類將具體實現在其基類中作為接口的操作。所以派生類實際上刻畫了一組子類的操作接口的通用語義,這些語義也傳給子類,子類可以具體實現這些語義,也可以再將這些語義傳給自己的子類。

      (3)使用抽象類時注意:

    抽象類只能作為基類來使用,其純虛函數的實現由派生類給出。如果派生類中沒有重新定義純虛函數,而只是繼承基類的純虛函數,則這個派生類仍然還是一個抽象類。如果派生類中給出了基類純虛函數的實現,則該派生類就不再是抽象類了,它是一個可以建立對象的具體的類。

    抽象類是不能定義對象的。

一、純虛函數定義

 純虛函數是一種特殊的虛函數,它的一般格式如下:

 

  class <類名>

 

  {

 

  virtual <類型><函數名>(<參數表>)=0;

 

  …

 

  };

 

  在許多情況下,在基類中不能對虛函數給出有意義的實現,而把它聲明為純虛函數,它的實現留給該基類的派生類去做。這就是純虛函數的作用。

 

  純虛函數可以讓類先具有一個操作名稱,而沒有操作內容,讓派生類在繼承時再去具體地給出定義。凡是含有純虛函數的類叫做抽象類。這種類不能聲明對象,只是作為基類為派生類服務。除非在派生類中完全實現基類中所有的的純虛函數,否則,派生類也變成了抽象類,不能實例化對象。

 

二、純虛函數引入原因

    1、為了方便使用多態特性,我們常常需要在基類中定義虛擬函數

 

  2、在很多情況下,基類本身生成對象是不合情理的。例如,動物作為一個基類可以派生出老虎、孔 雀等子類,但動物本身生成對象明顯不合常理。

  為了解決上述問題,引入了純虛函數的概念,將函數定義為純虛函數(方法:virtual ReturnType Function()= 0;)。若要使派生類為非抽象類,則編譯器要求在派生類中,必須對純虛函數予以重載以實現多態性。同時含有純虛函數的類稱為抽象類,它不能生成對象。這樣就很好地解決了上述兩個問題。

         例如,繪畫程序中,shape作為一個基類可以派生出圓形、矩形、正方形、梯形等, 如果我要求面積總和的話,那么會可以使用一個 shape * 的數組,只要依次調用派生類的area()函數了。如果不用接口就沒法定義成數組,因為既可以是circle ,也可以是square ,而且以后可能加上rectangle,等等.

 

三、相似概念

      1、多態性

 

  指相同對象收到不同消息或不同對象收到相同消息時產生不同的實現動作。C++支持兩種多態性:編譯時多態性,運行時多態性。

 

  a.編譯時多態性:通過重載函數實現

 

  b 運行時多態性:通過虛函數實現。

 

  2、虛函數

 

  虛函數是在基類中被聲明為virtual,並在派生類中重新定義的成員函數,可實現成員函數的動態重載

 

  3、抽象類

 

  包含純虛函數的類稱為抽象類。由於抽象類包含了沒有定義的純虛函數,所以不能定義抽象類的對象。

四、其他

重載是不是多態?

第一種說法

  重載是一種是多態(如C++),有四種形式的多態:

 

  1.虛函數多態

 

  2模板多態

 

  3重載

 

  4轉換

 

  所謂的動態和靜態區分是另一種基於綁定時間的多態分類,嚴格來說,重載是編譯時多態,即靜態多態,根據不同類型函數編譯時會產生不同的名字如int_foo和char_foo等等,以此來區別調用。故重載仍符合多態定義——通過單一標識支持不同特定行為的能力,只是重載屬於靜態多態,而不是通過繼承和虛函數實現的動態多態。

第二種說法

  重載(overload)和多態無關,真正和多態相關的是覆蓋(override)。

 

  當派生類重新定義了基類的虛擬方法后,基類根據賦給它的不同的派生類引用,動態地調用屬於派生類的對應方法,這樣的方法調用在編譯期間是無法確定的。因此,這樣的方法地址是在運行期綁定的(動態綁定)。

 

  重載只是一種語言特性,是一種語法規則,與多態無關,與面向對象也無關。

 

  不過針對所謂的第二種重載,有一個專門的名詞--重寫或重定義。重載與重寫的區別就在於是否覆蓋,重寫一般多發生在不同的類且存在繼承關系之間,而重載多是在一個類里或者一塊代碼段里。

C++中的重載

  函數重載:

 

  函數重載就是函數名稱相同,但定義卻不同。函數重載使得程序員可以將一系列的函數族定義為一個統一的界面,但是卻可以處理不同類型數據或接受不同個數的參數。這實現了統一接口,不同定義的思想。

 

  流的重載:

 

  C++的流提取運算符>>和就插入運算符<<是C++類庫提供的輸入輸出(I/O)操作符。系統與定義了輸入流類istream和輸出流類ostream,cin和cout分別是istream和ostream的對象。iostream頭文件中已經對>>和<<進行了重載,使得它能用來輸入/輸出標准類型的數據。但如果是自己定義類型,就需要重載在這兩個運算符,以便它們能輸入/上歲數出該自定義類型。格式如下:

 

  流插入的重載:ostream &operator<<(ostream &,自定義類 &);

 

  流提取的重載:istream &operator>>(istream &,自定義類 &);

 

  運算符的重載:

 

  運算符的重在就是對運算符的重新定義,即一個運算符可以用於多種數據類型的運算中。運算符的重載在實際編程中使用很普遍,例如,“+”運算符既可以用於整數加,也可以用於浮點加,甚至是字符串的鏈接。格式如下:

 

  type operator sign (參數列表);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM