1、虛函數、覆蓋、多態安全
虛函數:在定義時添加virtual關鍵字的成員函數,叫虛函數函數
覆蓋:在子類中實現與父類中虛函數相同的函數,那麼子類中的成員函數會覆蓋父類中的成員函數this
不一樣於隱藏,隱藏是在父子類之間名字相同的標識符,只要不夠成覆蓋,就是隱藏。子類會隱藏父類中的同名函數spa
多態:若是子類中的成員函數對父類中的成員函數進行了覆蓋,那麼當一個指向子類的父類指針或引用了子類的父類引用,在調用此同名函數時會調用子類中的函數,而不是父類中的虛函數,這種語法現象叫多態。設計
多態的意義在於同一種類發出同一種調用而產生不一樣的反映指針
2、覆蓋、重載、隱藏的條件對象
覆蓋(重寫):繼承
a、不在同一做用域,分別在基類和派生類接口
b、函數名、參數、返回值相同內存
c、基類函數必須有virtual關鍵字
d、訪問修飾符能夠不一樣
重載:
a、在同一做用域下
b、函數名相同,參數不一樣
c、返回值能夠不一樣
隱藏:
a、在不一樣做用域中
b、函數名相同
c、在基類和派生類中只要不構成覆蓋就是隱藏
3、多態的條件
一、派生類必須重寫基類的虛函數。
二、經過基類指針或引用調用基類的虛函數(該虛函數派生類必需要重寫)
三、當指針或引用已經構成多態時,此時調用成員所傳的this指針再調用成員函數時也構成多態
四、在子類的構造函數執行前會先調用父類的構造函數,若是調用被覆蓋的虛函數,因爲子類還沒構造完成,所以只能是調用父類中的虛函數構造函數在進入函數體執行時,類中看得見的資源已經所有構造完成
五、在子類的析構函數執行完成後會再調用父類的析構函數,若是調用被覆蓋的虛函數,因爲子類已經開始析構完成已經不能算是完整的子類了,所以只能調用父類中的虛函數
4、純虛函數和抽象類
一、純虛函數
class A
{
public:
virtual void test(void) = 0;
virtual void test(void) const = 0;
};
a、純虛函數不須要被實現,若是非要實現也不能在類中,必需要在類外(虛函數)
b、純虛函數若是想調用必須在子類中覆蓋,而後以多態的方式調用
二、抽象類
成員函數中有純虛函數的叫抽象類,這種類不能建立對象。
若是子類繼承了抽象類,則必須把父類中的純虛函數覆蓋了,不然他也變成了抽象類不能被實例化
所以抽象類只能以指針或引用的方式指向子類來調用非純虛函數
三、純抽象類
全部的成員函數都是純虛函數,這種類叫純抽象類
面向對象的四大特性:抽象、封裝、繼承、多態
純抽象類是類封裝的過程,同時抽象類也能夠當作一個統一的接口
6、虛函數表
一、什麼是虛函數表,當一個類中有虛函數時,編譯器會爲這個函數分配一個專門記錄這些的虛函數表,在類中會有一個隱藏的指針成員指向這張表
二、如何證實這張表存在
有虛函數的類會比沒有虛函數的類(相同的)多4字節,還會添加補齊和對其
三、一個類只有一張虛函數表,全部對象共享一張虛函數表
四、通常對象的前4字節是指向虛函數表的指針
7、動態類型綁定(多態)
一、當使用父類指針或引用指向子類時,編譯器並無當即生成調用函數的指針,而是生成了一段代碼,用於檢查指針指向的真正的對象是什麼類型
二、在代碼真正運行時才經過對象的指針找到指向虛函數的成員指針
三、再經過成員指針訪問到虛函數表,再從中找到調用的函數地址
四、使用多態會產生額外的一些代碼和調用,所以使用多態會下降代碼的執行速度
9、虛析構
一、若是經過父類指針或引用指向子類對象,當使用delete釋放對象時,此時只能調用父類的析構函數,若是子類中使用new/malloc申請了內存資源,那麼將致使內存泄漏
二、解決方法就是把父類的析構函數設置爲虛函數
三、在設計類時若是析構函數什麼都須要作,編譯器也會生成一個空的析構函數,但這樣會讓繼承它的子類會有安全隱患
四、最好把全部的析構函數都設置爲虛函數