日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++_虚继承_虚函数_纯虚函数(多继承的二义性,多态)

發(fā)布時間:2024/7/5 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++_虚继承_虚函数_纯虚函数(多继承的二义性,多态) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

基本信息

每一個類都有一個虛表,以及虛表指針; 虛表的內(nèi)容是編譯器決定的,虛表中用于存放虛函數(shù)的指針, 程序運行時的類型信息等;
每個多態(tài)對象都存放著一個指向當前類型的虛表的指針, 該指針在構(gòu)造函數(shù)中被賦值, 一般來說當調(diào)用當前這個類的構(gòu)造函數(shù), 則虛表指針就指向當前類的虛表

虛繼承

用于解決多重繼承的過程中成員訪問的二義性(菱形繼承)
格式:class 類名 : virtual 繼承方式 基類類名
注:在虛繼承的過程中,編譯器會為子類創(chuàng)建一個虛表,以及一個虛基表指針(占用對象空間)指向虛表(不占用對象空間)
例:

#include<iostream> using namespace std; class A{private:int a;public:A(){cout<<"A()"<<endl;}~A(){cout<<"~A()"<<endl;} }; class B:virtual public A{private:int b;public:B(){cout<<"B()"<<endl;}~B(){cout<<"~B()"<<endl;} }; class C:virtual public A{private:int c;public:C(){cout<<"C()"<<endl;}~C(){cout<<"~C()"<<endl;} }; class D:public B,public C{private:int d;public:D(){cout<<"D()"<<endl;}~D(){cout<<"~D()"<<endl;} }; int main(){//64位虛表指針為8個字節(jié) cout<<sizeof(A)<<endl; //輸出4 cout<<sizeof(B)<<endl;//輸出 B本身(4)+A(4)+虛表指針(8)=16 cout<<sizeof(C)<<endl;//輸出與B相同 cout<<sizeof(D)<<endl;//輸出 B+C+D本身-A(一份的A)=32

上述代碼中: B, C虛繼承于A, 他們二者”共享”一份A(用集合的方式理解,A屬于B, C的交集), 當D繼承B,C的時候只會保留一份A在D中
若未采用虛繼承在D創(chuàng)建對象的時候,會創(chuàng)建2份的A,出現(xiàn)冗余, 使用虛繼承繼承基類的兩個虛指針,并調(diào)整虛指針與虛基類首地址的偏移量,使得繼承過程中只保留一份的A
當使用虛繼承的過程中,虛基類被共享,無論繼承多少次,虛表指針都只會指向一份的虛基類,對象模型中只會存有一份的虛基類對象

虛函數(shù)

在基類中使用virtual修飾的成員函數(shù),當函數(shù)聲明為虛函數(shù)時,告訴編譯器不要靜態(tài)鏈接到該函數(shù),而是根據(jù)程序的運行過程中動態(tài)地根據(jù)該對象類型來調(diào)用函數(shù), 就所謂的多態(tài)
注:當基類成員函數(shù)聲明為virtual, 子類進行對virtual重寫,那么重寫后的函數(shù)都為虛函數(shù)(即使該函數(shù)前面沒寫virtual關(guān)鍵字); 虛函數(shù)成員的virtual關(guān)鍵字只能出現(xiàn)在類中定義的函數(shù)原型前面, 不能出現(xiàn)在類外成員函數(shù)實現(xiàn)的前面
虛函數(shù)一般不聲明為inline函數(shù), inline函數(shù)屬于靜態(tài)綁定, 而虛函數(shù)的調(diào)用是動態(tài)綁定, 如果將虛函數(shù)作為inline函數(shù)也不會出錯
構(gòu)造函數(shù), 靜態(tài)函數(shù), 復(fù)制構(gòu)造函數(shù)不可做為虛函數(shù), 原因只在于虛函數(shù)為動態(tài)綁定;

#include <iostream> using namespace std; class Shape {protected:int width, height;public:Shape( int a=0, int b=0){width = a;height = b;}virtual int area(){//編譯時,生成一個虛表以及虛表指針cout << "Parent class area :" <<endl;return 0;} }; class Rectangle: public Shape{public:Rectangle( int a=0, int b=0):Shape(a, b) { }virtual int area () {//為虛函數(shù),即使沒有關(guān)鍵字virtualcout << "Rectangle class area :" <<endl;return (width * height); } }; class Triangle: public Shape{public:Triangle( int a=0, int b=0):Shape(a, b) { }virtual int area (){cout << "Triangle class area :" <<endl;return (width * height / 2); } }; int main( ) {Shape *shape;Rectangle rec(10,7);Triangle tri(10,5);shape = &rec;shape->area(); // 調(diào)用矩形的求面積函數(shù) areashape = &tri;// 存儲三角形的地址shape->area(); // 調(diào)用三角形的求面積函數(shù) areareturn 0; }

此時,編譯器看的是指針的內(nèi)容(決定了能夠調(diào)用哪些虛函數(shù)),它指向的對象類型決定了該調(diào)用誰的虛函數(shù)。因此,由于 tri 和 rec 類的對象的地址存儲在 *shape 中,所以會調(diào)用各自的 area() 函數(shù)。

動態(tài)綁定的底層實現(xiàn):
虛表指針需要初始化才能調(diào)用虛函數(shù),虛表指針在構(gòu)造對象的時候初始化(初始化順序與構(gòu)造函數(shù)的調(diào)用順序一致),當構(gòu)造函數(shù)發(fā)現(xiàn)BASE具有虛函數(shù),虛指針指向BASE的虛表中的虛函數(shù),當執(zhí)行構(gòu)造子類對象的時候,子類中虛指針指向子類虛表中的虛函數(shù);當對象創(chuàng)建好后,虛表指針指向的是子類的虛函數(shù),從而對象調(diào)用虛函數(shù)時,實現(xiàn)多態(tài)

注:虛表會被繼承,當子類重寫虛函數(shù)的時候,那么虛表中的虛函數(shù)地址則會改變
在動態(tài)分配內(nèi)存的時候,析構(gòu)函數(shù)必須是虛函數(shù)(利用動態(tài)綁定)防止不會調(diào)用所需的析構(gòu)函數(shù)
使用虛函數(shù)意味著多態(tài),多態(tài)必須具備的三個條件:繼承關(guān)系; 繼承的過程中必須有同名的虛函數(shù); 存在基類的指針或引用,通過該指針或引用調(diào)用虛函數(shù)

虛析構(gòu)函數(shù)
析構(gòu)函數(shù)可作為虛函數(shù), 方便父類指針知道該調(diào)用哪個子類的析構(gòu)函數(shù)(析構(gòu)函數(shù)的多態(tài))
一般情況下, 如果涉及到多態(tài), 則將析構(gòu)函數(shù)設(shè)置為virtual

#include<iostream> using namespace std; class BASE{public:~BASE(){cout<<"父類析構(gòu)函數(shù)"<<endl;} }; class Derive:public BASE{public:Derive(){} ~Derive(){cout<<"子類析構(gòu)函數(shù)"<<endl;} }; int main(){BASE *b=new Derive();delete b;return 0; }

//上述代碼輸出:父類析構(gòu)函數(shù),由于BASE指針偏移量的問題,未將父類析構(gòu)函數(shù)設(shè)置為虛析構(gòu)函數(shù),導(dǎo)致靜態(tài)綁定只會釋放父類內(nèi)存區(qū),不會釋放子類內(nèi)存區(qū),導(dǎo)致內(nèi)存泄漏;
為了避免這種錯誤應(yīng)將父類,子類的析構(gòu)函數(shù)設(shè)置為virtual,則會解決這個問題
注: 子類對象析構(gòu)函數(shù)的調(diào)用順序,先調(diào)用子類析構(gòu)函數(shù), 然后調(diào)用父類析構(gòu)函數(shù), 調(diào)用順序與構(gòu)造函數(shù)調(diào)用順序相反

純虛函數(shù) (抽象類)

在基類重定義純虛函數(shù),以便在派生類中重新定義該函數(shù)來適用于對象,純虛函數(shù)就相當于接口,用于規(guī)范派生類行為
包含純虛函數(shù)的類是抽象類,不能實例化, 當子類繼承抽象類時,若沒有實現(xiàn)純虛函數(shù), 則子類還是抽象類
語法: virtual void function()=0;
等于0表示沒有函數(shù)體,

class Shape {protected:int width, height;public:Shape( int a=0, int b=0){width = a;height = b;}// pure virtual functionvirtual int area() = 0; };

注: C++中,父類中的純虛函可以有實現(xiàn)方式, 但是編譯器會忽略, 父類依舊為抽象類, 由于抽象類不能實例化, 但是可以定義指針或引用, 通過指針和引用依舊能實現(xiàn)多態(tài), 與Java中抽象類實現(xiàn)多態(tài)的方式一致
總結(jié):

  • 虛繼承: 虛表基表, 虛基指針主要用來記錄偏移量(虛基指針在虛基表上),以保證多繼承的過程中只復(fù)制一份的基類
  • 虛函數(shù): 虛表,虛指針主要用于指向虛函數(shù)(虛指針指向虛表中的虛函數(shù)地址)
  • 純虛函數(shù): 就是接口, 規(guī)范子類行為

總結(jié)

以上是生活随笔為你收集整理的C++_虚继承_虚函数_纯虚函数(多继承的二义性,多态)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久视频在线 | 在线观看亚洲免费视频 | 久久一区国产 | 老太脱裤让老头玩ⅹxxxx | 久草a在线 | 欧美在线一区二区三区四区 | 亚洲第一香蕉网 | 成人午夜免费视频 | 性午夜| 啪啪免费av | 美女福利在线视频 | 少妇视频在线观看 | 午夜天堂影院 | 国产精品久久久久久一区 | 日韩欧美黄色大片 | 青青伊人av| 国产成人免费在线 | 在线免费观看一区二区三区 | 国产盗摄精品一区二区酒店 | 老色鬼av | 国产成人午夜精品无码区久久 | 色九月婷婷 | 成人性视频网 | 一区二区伦理片 | 久久成人18免费观看 | 精品日本一区二区三区在线观看 | 久久精工是国产品牌吗 | 最新视频 - 8mav | 欧美三级午夜理伦三级老人 | 成人日韩在线 | 欧美福利一区二区三区 | 永久黄色网址 | 久久久亚洲一区二区三区 | 99色网站| 制服诱惑一区 | 欧美精品第一区 | 欧美日韩丝袜 | 色先锋av| 一级黄色美女视频 | 丁香综合网 | 91成人免费看 | 色婷婷久久久亚洲一区二区三区 | 日韩美女激情 | 成年女人毛片 | 乱老熟女一区二区三区 | 91精品入口| 操她视频在线观看 | 伊人网综合网 | 日韩av不卡一区 | 国产精品一区二区亚洲 | 亚洲成人黄色小说 | 麻豆91在线观看 | 亚洲视频日韩 | 91在线免费观看网站 | av免费大片 | 国产极品美女在线 | 亚洲精选av | a毛片成人 | 国产乱强伦一区二区三区 | 韩日精品在线 | 国产农村妇女毛片精品 | 久久潮| 国产免费黄网站 | 五月天av网站 | 狠狠操狠狠操狠狠操 | 黄色av导航| 久草免费新视频 | 国产模特av私拍大尺度 | 不卡视频在线观看免费 | 天天躁日日躁狠狠躁欧美 | 92av视频| 欧美视频在线观看一区二区 | 一区二区三区国 | www.奇米.com | a免费看| 最新亚洲精品 | 国模无码国产精品视频 | 中文字幕亚洲在线观看 | 中文字幕有码视频 | 五月天婷婷综合 | 亚洲欧美一级 | 97视频免费在线观看 | 一区二区三区四区视频在线观看 | 亚洲影视在线 | 亚洲三区在线播放 | 欧美性生交xxxxx久久久 | 久久久男人天堂 | 久久综合久久综合久久 | 欧美精品一区二区蜜桃 | jizz黄| 在线看片中文字幕 | 91免费网站| 91免费高清在线观看 | 久国产| 亚洲作爱 | 欧美一级一区二区 | 欧美日韩99 | 用我的手指扰乱你 | 日韩视频在线一区二区 |