C++的三大特性是什么?封裝、繼承與多態,那么今天這篇文章小編就來介紹一下,如何用C語言實現C++的這三個特性。
1.封裝
何為封裝?
在面向對象的思想中,將數據和對數據的操作封裝在一起——即類。
類只對外界開放接口(即有權訪問的函數接口),而將接口的實現細節和該類的一些屬性(變量)隱藏起來,達到數據的抽象性(使具有相同行為的不同數據可以抽象為同一個類)、隱藏性和封裝性。
我們知道,C語言中有struct結構體類型,能夠將多種數據類型封裝在一起,然而如何將對數據的操作一起封裝進來呢?——函數指針。
對,顯然我們可以使用函數指針。如下就是名為pfun,指向一個返回值為空、形參列表為空的函數指針:
函數指針格式簡介
那么問題已經得到解決:將類中的函數以函數指針的形式存放在C的結構體中,即可實現封裝(此處未討論訪問權限問題,小編仍在思考較好的方法,大家如果有好的建議記得留言噢n(*≧▽≦*)n!)
如下圖所示,結構體AchievePackage中有成員變量_a和兩個函數指針,在InitStruct函數中被賦予兩個函數的地址(函數名即為其地址,也可為&fun1,得到的值一樣),故在此處InitStruct函數相當於該結構體的構造函數,既可以初始化其成員變量_a的值,也在對象定義的同時為其函數指針賦值(需顯示調用)
C語言實現封裝詳解
2.繼承
顧名思義,就像孩子會繼承父母的一些性格或特點,兩個類如果存在繼承關系,其子類必定具有父類的相關屬性(即變量)和方法(即函數)。
在C++中,如果想要類B去繼承類A,需要在B定義時增加如下語句:
C++繼承簡介
那么C語言要如何實現此特性呢?講到這里,大家可以想到什么?
【組合】:如果僅僅是想用一個已有類的一些方法去輔助新生成的類,組合是一個很好的方案,即在新類中直接定義已有類的對象,通過該對象的一些方法去輔助新類的操作。
它與繼承相比:
-
繼承即“屬於(is a)”關系,而組合是“包含(has a)”關系。
-
繼承是復用原類,並對其進行擴展,而包含僅僅是組合在一起。
-
如我們可以用普通車輛(所有車的共同特性)擴展(繼承)出公交車、面包車、越野車等等,它們都屬於普通車輛;也可以用發動機、排氣筒、輪子等組合出一輛車,它們都包含在車輛中。
下面我們就用“組合”去實現一下C語言中的繼承:
C語言實現繼承代碼
3.多態
在C++中,多態是通過父類的指針或引用,調用了一個在父類中是virtual類型的函數,實現動態綁定機制。我們知道,若想使用父類的指針/引用調用子類的函數,需要在父類中將其聲明為虛函數(virtual),且必須與子類中的函數參數列表相同(包括參數個數、類型、順序),返回值也相同(若不同為協變的情況,需要各自返回各自類的指針/引用)。
那么如何用C實現多態?
-
C++的多態是通過覆蓋實現的,即父類的函數被子類覆蓋了!
-
父類的該函數為虛函數,告訴父類的指針/引用,你調用這個函數的時候必須看一看你綁定的對象到底是哪個類的對象,然后去那個類里調用該函數!
So,覆蓋!我們用值的覆蓋,去改變函數指針,是否可以達到多態的效果呢?
C語言實現多態代碼
以上,便是C語言實現C++三大特性的全部內容。
需要注意的是:
-
畢竟是用C語言去實現本不屬於它的特性,一定會存在不可避免的付出,但我們可以通過不同的處理,盡量降低付出成本。
-
本文中未對訪問限定符public、protected、private進行討論