C++编程思想:继承与虚函数以及多态
生活随笔
收集整理的這篇文章主要介紹了
C++编程思想:继承与虚函数以及多态
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 簡介
- 實現虛函數多態的技術原理
- 對象切邊
- 析構函數和構造函數中的虛函數
- 使用繼承的類的析構函數應該使用虛函數修飾符
簡介
繼承與虛函數與多態是渾然一體的三個概念,父類中虛函數可以表現出多態特性,具體是將子類的地址傳遞給指向父類的指針(類型向上轉換),通過這樣的指針調用虛函數依然會調用到子類中的這個虛函數的實現,這就是多態。
實現虛函數多態的技術原理
C++編譯器在每個包含虛函數類的對象中隱匿生成了一個指針vptr,這個指針指向一張虛函數表,虛函數表中記錄著每個虛函數距離當前對象起始地址的偏移量。當調用虛函數時,通過這個指針找到虛函數距離當前對象的偏移量確定此函數,此時如果傳遞的時子對象地址,自然會調用子函數中的虛函數實現體。
對象切邊
當通過指針傳遞地址時可以實現多態,但是如果是傳值的話,就不會出現多態,出現的是子類對象被強制轉換為父類對象,丟失子類對象多余成員。
析構函數和構造函數中的虛函數
析構函數和構造函數中的虛函數調用都會本地函數,這樣做的一個原因是,當構造函數沒有完成時,這個類對象隱匿的vptr指針還沒有構建完成,另外這樣實現也有很多好處。
使用繼承的類的析構函數應該使用虛函數修飾符
析構函數使用虛函數修飾符會保證多態時,正確的調用析構函數,具體可見代碼實現。
#include<iostream> #include<string> using namespace std;class noVirtual { public:string name;string getName() {name = "nV";return name;}; };class BasePet { public:string name;virtual string getName() {cout << "this is BasePet" << endl;name = "basePet";return name;};~BasePet() {cout << "~BasePet" << endl;} };class Dog :public BasePet { public:virtual float getSpeed() {return 1.0;};string getName() {cout << "this is dog" << endl;name = "dog";return name;}; };class People { public:People(){getName();}virtual void getName(){cout << "this is in people()" << endl;}~People() {cout << "this is in ~people()" << endl;} };class Man:public People { public:Man(){getName();}void getName(){cout << "this is in Man()" << endl;}virtual ~Man() {cout << "this is in ~Man()" << endl;} };class Son :public Man { public:Son(){getName();}void getName(){cout << "this is in Son()" << endl;}~Son() {cout << "this is in ~Son()" << endl;} };int main () {/*//確定虛函數確實多了一個虛指針noVirtual nV;BasePet bP;Dog dG;cout << "size of nV " << sizeof(nV) << endl;cout << "size of bP " << sizeof(bP) << endl;cout << "size of dG " << sizeof(dG) << endl;int* p;cout << "size of 一個指針大小 " << sizeof(p) << endl;//使用虛函數機制 多態BasePet* bPtr = new Dog();bPtr->getName();delete bPtr;//對象切片,當不使用地址傳遞時,虛函數機制失效,子類對象強制轉化為父類對象,調用父類函數BasePet bPO;Dog dGO;bPO = dGO;bPO.getName();//構造函數和虛構函數中調用析構函數都會調用本地版本的函數Son s;*///析構函數應該設計成虛函數,否則會有內存泄露的風險People* pp = new Son();delete pp; //直接調用了people的析構函數Man* m = new Son();delete m; //從son的析構函數開始調用}總結
以上是生活随笔為你收集整理的C++编程思想:继承与虚函数以及多态的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++编程思想:父类函数隐藏
- 下一篇: C++编程思想:模板