多型按字面的意思就是多種形態,相同的方法呼叫,但是有不同的實現方式。多型性可以簡單地概括為「乙個介面,多種方法」。
c++有兩種多型形式:
靜態多型:也稱為編譯期間的多型,編譯器在編譯期間完成的,編譯器根據函式實參的型別(可能會進行隱式型別轉換),可推斷出要呼叫那個函式,如果有對應的函式就呼叫該函式,否則出現編譯錯誤。
靜態多型有兩種實現方式:
函式過載就像是有多種含義的動詞。例如:你可以在棒球場為球隊助威(root),也可以在地里種植(root)菌類植物。
根據上下文可以知道每種情況下,root的含義是什麼,同樣,c++中也通過上下文來確定同名函式的過載版本。
過載函式的關鍵是函式引數列表——也稱函式特徵標。包括:函式的引數數目和型別,以及引數的排列順序。所以,過載函式與返回值,引數名無關。
//
print()函式
void
print(const char* str,int width);
void
print(double i ,int width);
void
print(const char* str);
// 使用print()函式時,編譯器將根據所採取的用法使用有相應特徵標的原型
print("abc",12);
print(2.2,55);
print("def");
以下這種方式的過載是錯誤的
void print(const
char* str,int width);
int print(const
char* str,int width);
過載時返回值可以不同,但特徵標也必須不同。
為什麼c語言中沒有過載呢?
編譯器在編譯期間建立的乙個字串,用來指明函式的定義或原型。c和c++程式的函式在內部使用不同的名字修飾方式。
c編譯器的函式名修飾規則:
對於__stdcall呼叫約定,編譯器和鏈結器會在輸出函式名前加上乙個下劃線字首,函式名後面加上乙個「@」符號和其引數的位元組數,例如_functionname@number。__cdecl呼叫約定僅在輸出函式名前加上乙個下劃線字首,例如_functionname。__fastcall呼叫約定在輸出函式名前加上乙個「@」符號,後面也是乙個「@」符號和其引數的位元組數,例如@functionname@number。
c++編譯器的函式名修飾規則:
c++的函式名修飾規則有些複雜,但是資訊更充分,通過分析修飾名不僅能夠知道函式的呼叫方式,返回值型別,引數個數甚至引數型別。不管 __cdecl,__fastcall還是__stdcall呼叫方式,函式修飾都是以乙個「?」開始,後面緊跟函式的名字,再後面是參數列的開始標識和 按照引數型別代號拼出的參數列。對於__stdcall方式,參數列的開始標識是「@@yg」,對於__cdecl方式則是「@@ya」,對於__fastcall方式則是「@@yi」。參數列的拼寫代號如下所示:
x–void
d–char
e–unsigned char
f–short
h–int
i–unsigned int
j–long
k–unsigned long(dword)
m–float
n–double
_n–bool
u–struct
…. 所以,c++編譯器能識別函式特徵標的不同,從而實現過載。
函式模板是通用的函式描述,也就是說,使用泛型來定義函式,其中泛型可用具體的型別(int 、double等)替換。通過將型別作為引數,傳遞給模板,可使編譯器生成該型別的函式。
// 交換兩個值,但是不清楚是int 還是 double,如果不使用模板,則要寫兩份**
// 使用函式模板,將型別作為引數傳遞
template
t>
class
swa(t a,t b)
;
動態多型(動態繫結):即執行時的多型,在程式執行期間(非編譯期)判斷所引用物件的實際型別,根據其實際型別呼叫相應的方法。
1.通過基類型別的引用或者指標呼叫虛函式
首先搞清楚這個物件的型別:
2.必須是虛函式(派生類一定要重寫基類中的虛函式)
純虛函式是在基類中宣告的虛函式,它在基類中沒有定義,但要求任何派生類都要定義自己的實現方法。在基類中實現純虛函式的方法是在函式原型後加「=0」 。
包含純虛函式的類叫做抽象類(也叫介面類),抽象類不能例項化出物件。純虛函式在派生類中重新定義以後,派生類才能例項化出物件。
class a
;class b : public a
fun()
...};class c : public a
;
如果有很多類都繼承了這個基類,那麼每個物件中都要為建立基類消耗資源,此時出現了虛函式表。
對於有虛函式的類,編譯器都會維護一張虛函式表(虛表),物件的前四個位元組就是指向虛表的指標(虛表指標)。
虛函式表的建立分為兩種情況:
無覆蓋
基類中虛函式在派生類中不是虛函式
有覆蓋
class base
class derived : public base
基類的虛函式表沒有變化
通過基類的引用或指標呼叫,,呼叫基類還是派生類的虛函式,要根據執行時根據指標或引用實際指向或引用的型別確定,呼叫非虛函式時,則無論基類指向的是何種型別,都呼叫基類的函式
C 多型 靜態多型與動態多型
多型 顧名思義,多型就是多種形態,也就是對不同物件傳送同乙個訊息,不同物件會做出不同的響應。並且多型分為靜態多型和動態多型。靜態多型就是在系統編譯期間就可以確定程式執行到這裡將要執行哪個函式,例如 函式的過載,物件名加點操作符執行成員函式等,都是靜態多型,其中,過載是在形成符號表的時候,對函式名做了...
C 動態多型與靜態多型
c 中有兩種多型 動多型 執行期多型 和靜多型 編譯期多型 而靜多型主要通過模板來實現,巨集也是實現靜多型的一種途徑。模板不採用虛函式機制,所以所有呼叫在編譯期就可確定,因此它是靜態的。基於繼承和虛函式,多型的設計思想主要在於 對於幾個相關物件的型別,確定它們之間的乙個共同功能集 然後在基類中,把這...
靜態多型 動態多型
又稱編譯期多型,即在系統編譯期間就可以確定程式將要執行哪個函式。例如 函式過載,通過類成員運算子指定的運算。函式過載示例 class a a int x void f void f int x class b void f void f int x 以上,類a中兩個a 是函式過載,兩個f 是函式過載...