C++编程思想:继承与虚函数以及多态
文章目錄
- 簡介
- 實(shí)現(xiàn)虛函數(shù)多態(tài)的技術(shù)原理
- 對(duì)象切邊
- 析構(gòu)函數(shù)和構(gòu)造函數(shù)中的虛函數(shù)
- 使用繼承的類的析構(gòu)函數(shù)應(yīng)該使用虛函數(shù)修飾符
簡介
繼承與虛函數(shù)與多態(tài)是渾然一體的三個(gè)概念,父類中虛函數(shù)可以表現(xiàn)出多態(tài)特性,具體是將子類的地址傳遞給指向父類的指針(類型向上轉(zhuǎn)換),通過這樣的指針調(diào)用虛函數(shù)依然會(huì)調(diào)用到子類中的這個(gè)虛函數(shù)的實(shí)現(xiàn),這就是多態(tài)。
實(shí)現(xiàn)虛函數(shù)多態(tài)的技術(shù)原理
C++編譯器在每個(gè)包含虛函數(shù)類的對(duì)象中隱匿生成了一個(gè)指針vptr,這個(gè)指針指向一張?zhí)摵瘮?shù)表,虛函數(shù)表中記錄著每個(gè)虛函數(shù)距離當(dāng)前對(duì)象起始地址的偏移量。當(dāng)調(diào)用虛函數(shù)時(shí),通過這個(gè)指針找到虛函數(shù)距離當(dāng)前對(duì)象的偏移量確定此函數(shù),此時(shí)如果傳遞的時(shí)子對(duì)象地址,自然會(huì)調(diào)用子函數(shù)中的虛函數(shù)實(shí)現(xiàn)體。
對(duì)象切邊
當(dāng)通過指針傳遞地址時(shí)可以實(shí)現(xiàn)多態(tài),但是如果是傳值的話,就不會(huì)出現(xiàn)多態(tài),出現(xiàn)的是子類對(duì)象被強(qiáng)制轉(zhuǎn)換為父類對(duì)象,丟失子類對(duì)象多余成員。
析構(gòu)函數(shù)和構(gòu)造函數(shù)中的虛函數(shù)
析構(gòu)函數(shù)和構(gòu)造函數(shù)中的虛函數(shù)調(diào)用都會(huì)本地函數(shù),這樣做的一個(gè)原因是,當(dāng)構(gòu)造函數(shù)沒有完成時(shí),這個(gè)類對(duì)象隱匿的vptr指針還沒有構(gòu)建完成,另外這樣實(shí)現(xiàn)也有很多好處。
使用繼承的類的析構(gòu)函數(shù)應(yīng)該使用虛函數(shù)修飾符
析構(gòu)函數(shù)使用虛函數(shù)修飾符會(huì)保證多態(tài)時(shí),正確的調(diào)用析構(gòu)函數(shù),具體可見代碼實(shí)現(xiàn)。
#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 () {/*//確定虛函數(shù)確實(shí)多了一個(gè)虛指針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 一個(gè)指針大小 " << sizeof(p) << endl;//使用虛函數(shù)機(jī)制 多態(tài)BasePet* bPtr = new Dog();bPtr->getName();delete bPtr;//對(duì)象切片,當(dāng)不使用地址傳遞時(shí),虛函數(shù)機(jī)制失效,子類對(duì)象強(qiáng)制轉(zhuǎn)化為父類對(duì)象,調(diào)用父類函數(shù)BasePet bPO;Dog dGO;bPO = dGO;bPO.getName();//構(gòu)造函數(shù)和虛構(gòu)函數(shù)中調(diào)用析構(gòu)函數(shù)都會(huì)調(diào)用本地版本的函數(shù)Son s;*///析構(gòu)函數(shù)應(yīng)該設(shè)計(jì)成虛函數(shù),否則會(huì)有內(nèi)存泄露的風(fēng)險(xiǎn)People* pp = new Son();delete pp; //直接調(diào)用了people的析構(gòu)函數(shù)Man* m = new Son();delete m; //從son的析構(gòu)函數(shù)開始調(diào)用}總結(jié)
以上是生活随笔為你收集整理的C++编程思想:继承与虚函数以及多态的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++编程思想:父类函数隐藏
- 下一篇: C++编程思想:模板