作用:
什么是多態:調用同一個函數(接口)表現出不同的結果
多態按字面的意思就是多種形態。當類之間存在層次結構,并且類之間是通過繼承關聯時,就會用到多態。
C++ 多態意味著調用成員函數時,會根據調用函數的對象的類型來執行不同的函數。
函數重寫(函數覆蓋):
1. 函數名相同
2. 入參一樣,返回值相同
3. 作用域不一樣,一個位于基類,一個位于派生類。
4. 基類的函數必須加virutal,派生類的同名函數可以加可不加。
5. 訪問限定符可以不一樣
虛函數:
虛函數 是在基類中使用關鍵字 virtual 聲明的函數。在派生類中重新定義基類中定義的虛函數時,會告訴編譯器不要靜態鏈接到該函數。
我們想要的是在程序中任意點可以根據所調用的對象類型來選擇調用的函數,這種操作被稱為動態鏈接,或后期綁定。
純虛函數:
您可能想要在基類中定義虛函數,以便在派生類中重新定義該函數更好地適用于對象,但是您在基類中又不能對虛函數給出有意義的實現,這個時候就會用到純虛函數。
怎么樣實現多態?
1. 派生類重寫基類的虛函數
2. 通過基類的指針指向派生類對象,通過基類指針調用虛函數,可以保證接口高度統一
賦值兼容規則
基類的指針可以指向派生類對象,而派生類指針不能指向基類的對
象
純虛函數:虛函數 =0;
包含純虛函數的類叫抽象類,抽象類無法創建對象。函數重載、函數重寫(覆蓋)、函數隱藏的區別?
1、成員函數覆蓋(override,也稱重寫)
是指派生類重新定義基類的虛函數,特征如下:
A、不同的作用域(分別位于派生類與基類)
B、函數名字相同
C、參數相同
D、基類函數必須有virtual關鍵字,不能有static
E、返回值相同
F、重寫函數的權限訪問限定符可以不同
2、函數重載(overload)
是指函數名相同,參數不同(數量、類型、次序),特征如下:
A、相同的范圍(在同一個作用域中)
B、函數名字相同
C、參數不同
D、virtual 關鍵字可有可無
E、返回值可以不同靜態聯編(靜態鏈接)
是指在編譯階段就將函數實現和函數調用關聯起來,因此靜態聯編也叫早綁定,函數重載是早綁定
動態聯編(動態鏈接)
是指在程序執行的時候才將函數實現和函數調用關聯,因此也叫運行時綁定或者晚綁定。
C++中一般情況下聯編也是靜態聯編,但是一旦涉及到多態和虛擬函數就必須要使用動態聯編了
3、成員函數隱藏(也稱重定義,盡量不去寫)
A、不在同一個作用域(分別位于派生類與基類)
B、函數名字相同
C、返回值可以不同
D、參數不同。此時,不論有無 virtual 關鍵字,基類的函數將被隱藏(注意與重載的區別)
E、參數相同,但是基類函數沒有 virtual關鍵字。此時,基類的函數被隱藏(注意與覆蓋的區別)
多態的原理:虛函數表
通過基類的指針或引用調用虛函數,到底調用是基類的虛函數還是派生類重寫后的虛函數,
看的是對象,而不是指針的數據類型。
原因:虛函數的調用會查虛函數表,每個對象的虛函數表不一樣,調用的虛函數就不一樣。
虛析構
析構函數前為什么加virtual關鍵字?
只有虛函數的調用,是看對象不同查對象的虛函數表,其他看指針或引用的數據類型。
如果不在析構函數前加virtual ,在某些情況下會產生內存泄漏。推薦在析構函數前加virtual
構造函數前為什么加explicit關鍵字?
給單參數的構造函數前使用explicit關鍵字,阻止可能產生的隱式轉換:由成員變量類型轉換為類類型。