c++中類的三大特性是:繼承,封裝,多型。 因為近期寫**用到了類的多型性,所以在這裡再總結一下。關於多型的定義,我是參考大佬的文章再加上自己的理解得到以下內容的,大佬鏈結在此。
多型性可以簡單地概括為「乙個介面,多種方法」,雖然在c++中沒有介面(inte***ce)這個關鍵字的存在,但是可以通過多型來實現,多型的目的就是為了介面重用。c++多型性是通過虛函式(virtual)來實現的,虛函式允許子類重新定義成員函式,而子類重新定義父類的做法稱為覆蓋(override),或者稱為重寫。override要求函式名和引數列表和父類一致。override關鍵字是c++11之後加進去的,目的是確保在派生類中宣告的過載函式跟基類的虛函式有相同的簽名。example。
另外乙個在中文意思上容易與此混淆的c++方法叫做過載(overload),overload則是允許有多個同名的函式,而這些函式的引數列表不同,允許引數個數不同,引數型別不同,或者兩者都不同。只有override+virtual才算是多型,overload並不算是多型性。從編譯器角度來看,override+virtual實現的函式在預編譯的時候只會生成乙個預處理函式,但是overload會根據各種情況生成不同的預處理函式。
多型與非多型的實質區別就是函式位址是早繫結還是晚繫結。如果函式的呼叫,在編譯器編譯期間就可以確定函式的呼叫位址,並生產**,是靜態的,就是說位址是早繫結的。而如果函式呼叫的位址不能在編譯器期間確定,需要在執行時才確定,這就屬於晚繫結。多型最常見的用法就是宣告基類的指標,利用該指標指向任意乙個子類物件,呼叫相應的虛函式,可以根據指向的子類的不同而實現不同的方法。如果沒有使用虛函式的話,即沒有利用c++多型性,則利用基類指標呼叫相應的函式的時候,將總被限制在基類函式本身,而無法呼叫到子類中被重寫過的函式。因為沒有多型性,函式呼叫的位址將是一定的,而固定的位址將始終呼叫到同乙個函式,這就無法實現乙個介面,多種方法的目的了。
talk is cheap , show me the code.
/*
*** in parent.h file
*/using
namespace std;
class
parent
inline
const vector
getresources()
protected
: vectorint, wstring>> mnames;
vector mresources;
};
以上code是乙個基類的宣告,在基類的實現檔案中就寫乙個析構函式即可。這裡只有析構函式被宣告為了虛函式,那建構函式能不能宣告為虛函式呢?答案是不能。
**原因:**虛函式的實現是通過物件記憶體中的vptr來實現的。而建構函式是用來例項化乙個物件的,通俗來講就是為物件記憶體中的值做初始化操作。那麼在建構函式完成之前,也即還沒有進行初始化,此時vptr是沒有值的,也就無法通過vptr找到作為建構函式和虛函式所在的**區,所以建構函式只能以普通函式的形式存放在類所指定的**區中。而對於析構函式,當我們delete(a)的時候,如果析構函式不是虛函式,那麼呼叫的將會是基類base的析構函式。而當繼承的時候,通常派生類會在基類的基礎上定義自己的成員,此時我們當然希望可以呼叫派生類的析構函式對新定義的成員也進行析構。
上面的code中還涉及到了乙個概念,就是純虛函式virtual void initialize() = 0;
,純虛函式也是虛函式,它的區別在於宣告的時候賦值為0,純虛函式告訴編譯器要求子類必須overide這個函式才能編譯通過,正常虛函式的話即使子類沒有override這個虛函式也是可以編譯通過的。
接下來來看子類的實現:
/*
*** in child.h file
*/class
child
:public parent
;
在子類的宣告中,雖然虛函式的引數列表和返回型別都與父類一致,但是後面加上override是為了保證出現一些不必要的失誤,達不到override的需求。
/*
*** in child.cpp file
*/void child::
initialize()
}
在子類的定義中,實現了parent這個類的虛函式。
呼叫過程如下:
/*
***in main.cpp
*/auto mpeople = std::make_unique()
;mpeople-
>
initialize()
;//呼叫子類child的方法
auto
& names = mpeople-
>
getnames()
;auto
& resources = mpeople-
>
getresources()
;
這樣就可以實現類的多型。因為override是c++11新加入的關鍵字,所以這篇部落格就說的是c++11。
以上。
C 11新增的類功能
如果您提供了析構函式,複製建構函式或複製賦值運算子 那麼移動建構函式和移動賦值運算子將不會被自動提供 如果您提供了移動建構函式或移動賦值運算子 那麼複製建構函式和複製構造運算子將不會被自動提供 testclass explicit testclass const string newmessage ...
c 11類的靜態成員
一 類靜態成員和類成員之間的區別 1.靜態成員在類的所有物件中是唯一且共享的。2.靜態成員即使在類物件不存在的情況下也能使用。靜態成員只要使用類名加範圍解析運算子 就可以訪問。3.靜態成員分為靜態成員函式和靜態成員變數。4.靜態成員可以使用或訪問其他靜態成員。靜態成員不能使用或訪問該類的非靜態成員即...
c 11 型別推斷
當編譯器能夠在乙個變數的宣告時候就推斷出它的型別,那麼你就能夠用auto關鍵字來作為他們的型別 cpp view plain copy auto x 1 編譯器當然知道x是integer型別的。所以你就不用int了。接觸過泛型程式設計或者api程式設計的人大概可以猜出自動型別推斷是做什麼用的了 幫你...