最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++菱形繼承及解決方法詳解

 更新時(shí)間:2023年08月08日 10:45:09   作者:魏天樂(lè)大帥哥  
這篇文章主要介紹了C++菱形繼承及解決方法詳解,在多繼承結(jié)構(gòu)中,存在著很多問(wèn)題,比如從不同基類(lèi)中繼承了同名成員,派生類(lèi)中也定義了同名成員,這種二義性問(wèn)題很好解決,加上要訪(fǎng)問(wèn)的基類(lèi)的類(lèi)名限制就可以了,需要的朋友可以參考下

菱形繼承

繼承是類(lèi)和類(lèi)之間的關(guān)系,是代碼復(fù)用的重要手段,允許在保持原有類(lèi)結(jié)構(gòu)的基礎(chǔ)上進(jìn)行擴(kuò)展,創(chuàng)建的新類(lèi)與原有的類(lèi)類(lèi)似,只是多了幾個(gè)成員變量和成員函數(shù)。

需要注意的是:

1.若不表明是以何種方式繼承,使用關(guān)鍵字class時(shí)默認(rèn)是私有繼承,使用struct關(guān)鍵字時(shí)默認(rèn)公有繼承

2.上面的不可訪(fǎng)問(wèn)是指派生類(lèi)對(duì)象不管是在類(lèi)里還是類(lèi)外都不能不訪(fǎng)問(wèn)

在談菱形繼承之前,需要先了解單繼承和多繼承:

  • 單繼承是一個(gè)子類(lèi)只有一個(gè)直接父類(lèi)時(shí)稱(chēng)這個(gè)繼承關(guān)系是單繼承
  • 一個(gè)子類(lèi)有兩個(gè)或兩個(gè)以上的直接父類(lèi)時(shí)稱(chēng)這個(gè)繼承關(guān)系為多繼承
  • 繼承中子類(lèi)中成員的排列次序與繼承次序有關(guān)
  • (也就是說(shuō)先繼承的類(lèi),類(lèi)中成員的地址越靠下)

菱形繼承:

  • 兩個(gè)子類(lèi)同時(shí)繼承一個(gè)父類(lèi),而又有子類(lèi)同時(shí)繼承這兩個(gè)子類(lèi)

缺點(diǎn):

  • 導(dǎo)致數(shù)據(jù)冗余和二義性的問(wèn)題

解決方法:

  • 對(duì)造成二義性的屬性使用域訪(fǎng)問(wèn)限定符,這樣從本質(zhì)上并沒(méi)有解決二義性
  • 想要解決二義性和數(shù)據(jù)冗余,這就需要用到虛擬繼承。屬性只會(huì)生成一份,要調(diào)用它需要使用虛基表指針,虛基表指針指向虛基表,虛基表中存在偏移量,通過(guò)偏移量就可以找到共有的那個(gè)屬性。

封裝,繼承,多態(tài)。這是C++語(yǔ)言的三大特性,而每次在談到繼承時(shí)我們不可避免的要談到一個(gè)很重要的問(wèn)題——菱形繼承。

多繼承,呈菱形狀

在這里插入圖片描述

菱形繼承代碼:

class A 
{
public:
    A() {}
    int _a ;
};
class B :public A 
{
public:
    //會(huì)存在父的int a;
    B() {}
    int _b ;
};
class C :public A 
{
public:
   //會(huì)存在父的int a;
    C() {}
    int _c ;
};
class D :public B,public C 
{
public:
   //會(huì)存在父的int a;    問(wèn)題來(lái)了這個(gè)a是  父親b中的a 還是 父親c中的a -- 二義性;
   //父的int b;
   //父的int c;
    D() {}
    int _d ;
};
int main()
{
    D d;
    d.B::_a = 1;
    d.C::_a = 2;
    d._b = 3;
    d._c = 4;
    b._d = 5;
    cout << d._a << endl;//報(bào)錯(cuò)  提示b.a具有二義性
    return 0;
}

出現(xiàn)二義性變量的內(nèi)存布局

在這里插入圖片描述

可以看到上圖中紫色框兩部分,是出現(xiàn)二義性的兩份A::_a變量,編譯器無(wú)法自主確定需要用哪一個(gè),可以d::A_a 或者 d::B_a這樣使用;

應(yīng)對(duì)方案

虛繼承 vitrual

vitrual修飾使派生類(lèi)出現(xiàn)二義性的父類(lèi)繼承部分(菱形的腰部)

class A 
{
public:
    A() {}
    int _a ;
};
class B :virtual public A //virtual修飾
{
public:
    //父的int a;
    B() {}
    int _b;
};
class C :virtual public A  //virtual修飾
{
public:
   //父的int a;
    C() {}
    int _c ;
};
class D :public B,public C 
{
public:
    //自己的 int a;(二義性的父親繼承經(jīng)virtual修飾)
   //父的int b;
   //父的int c;
    D() {}
    int _d;
};
int main()
{
    D d;
    d.B::_a = 1;
    d.C::_a = 2;
    d._b = 3;
    d._c = 4;
    b._d = 5;
    cout << d._a << endl;//沒(méi)問(wèn)題,輸出2,這個(gè)2是D類(lèi)成員通過(guò)繼承,使得d自己獨(dú)有且只有一份的 A::_a成員變量;
    return 0;
}

解決二義性變量?jī)?nèi)存布局–虛基表

在這里插入圖片描述

可以看到原先存放兩個(gè)二義性數(shù)據(jù)A::a和B::a的位置,變成了一個(gè)地址?

這個(gè)兩個(gè)地址就叫虛基表指針;

通過(guò)對(duì)虛基表的進(jìn)一步內(nèi)存研究,發(fā)現(xiàn)了虛基表緊著得下一個(gè)位置存放了一個(gè)偏移量,這個(gè)偏移量是存放該虛基表指針的內(nèi)存位置,與當(dāng)前派生類(lèi)獨(dú)有一份的成員變量_a之間的偏移長(zhǎng)度;

這樣我們直接使用d::a的時(shí)候,因?yàn)楠?dú)有一份,也不會(huì)出現(xiàn)數(shù)據(jù)二義性的問(wèn)題了;

注意,這和多態(tài)中的虛表(虛函數(shù)表兩回事)

其次,虛基表的指針,經(jīng)過(guò)測(cè)試,也是某個(gè)多繼承派生類(lèi)的多對(duì)象共用的;

eg: D d1,d2; 其中d1,d2兩個(gè)對(duì)象 上圖的這兩張?zhí)摶碇羔樖且粯拥模蚝芎?jiǎn)單,D類(lèi)類(lèi)型都一樣,那么某個(gè)位置起,到另一個(gè)相對(duì)位置偏移量肯定是固定的!

(同類(lèi)型的虛表指針也如此,復(fù)用節(jié)省空間嘛)

感悟

繼承,多態(tài)無(wú)疑為我們創(chuàng)造了很多的價(jià)值,但是像菱形繼承這種弊端也是存在的,本質(zhì)是多繼承而引起的問(wèn)題,在一些語(yǔ)言禁止了多繼承的行為,總之有利有弊,雖然C++允許了多繼承,但還是盡量別寫(xiě)多繼承這種模式,復(fù)雜度和出現(xiàn)問(wèn)題的概率都很大;

關(guān)于代碼復(fù)用等的另一種關(guān)系-組合

繼承是每個(gè)派生類(lèi)都能相對(duì)于繼承is-a的關(guān)系; 每個(gè)派生類(lèi)對(duì)象都是一個(gè)基類(lèi)對(duì)象; 耦合度高

在這里插入圖片描述

優(yōu)先考慮組合has-a的關(guān)系; eg: 汽車(chē)-輪胎,has-a,組合(class 輪胎 作為class 車(chē)的成員嵌套) 耦合度低

在這里插入圖片描述

到此這篇關(guān)于C++菱形繼承及解決方法詳解的文章就介紹到這了,更多相關(guān)C++菱形繼承內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解C++?STL模擬實(shí)現(xiàn)list

    詳解C++?STL模擬實(shí)現(xiàn)list

    這篇文章主要為大家詳細(xì)介紹了C++如何模擬實(shí)現(xiàn)STL容器list,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++有一定幫助,需要的可以參考一下
    2023-01-01
  • 使用C語(yǔ)言實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)

    使用C語(yǔ)言實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)

    這篇文章主要介紹了使用C語(yǔ)言實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C++實(shí)現(xiàn)鄰接表頂點(diǎn)的刪除

    C++實(shí)現(xiàn)鄰接表頂點(diǎn)的刪除

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)鄰接表頂點(diǎn)的刪除,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C語(yǔ)言詳細(xì)講解位運(yùn)算符的使用

    C語(yǔ)言詳細(xì)講解位運(yùn)算符的使用

    C語(yǔ)?既具有?級(jí)語(yǔ)?的特點(diǎn),?具有低級(jí)語(yǔ)?的特性,如?持位運(yùn)算就是其具體體現(xiàn)。這是因?yàn)椋珻語(yǔ)?最初是為取代匯編語(yǔ)?設(shè)計(jì)系統(tǒng)軟件?設(shè)計(jì)的,因此C語(yǔ)?必須?持位運(yùn)算等匯編操作。位運(yùn)算就是對(duì)字節(jié)或字內(nèi)的?進(jìn)制數(shù)位進(jìn)?測(cè)試、抽取、設(shè)置或移位等操作
    2022-04-04
  • C++實(shí)踐排序函數(shù)模板項(xiàng)目的參考方法

    C++實(shí)踐排序函數(shù)模板項(xiàng)目的參考方法

    今天小編就為大家分享一篇關(guān)于C++實(shí)踐排序函數(shù)模板項(xiàng)目的參考方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-02-02
  • 使用C++繪制GDI位圖的基本編寫(xiě)實(shí)例

    使用C++繪制GDI位圖的基本編寫(xiě)實(shí)例

    這篇文章主要介紹了使用C++繪制GDI位圖的基本編寫(xiě)實(shí)例,一般來(lái)說(shuō)適用于Windwos下的C++的GUI編程,需要的朋友可以參考下
    2015-12-12
  • QT 如何實(shí)現(xiàn)時(shí)間的獲取

    QT 如何實(shí)現(xiàn)時(shí)間的獲取

    這篇文章主要介紹了QT 如何實(shí)現(xiàn)時(shí)間的獲取,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-04-04
  • C++強(qiáng)制轉(zhuǎn)換與智能指針示例詳解

    C++強(qiáng)制轉(zhuǎn)換與智能指針示例詳解

    這篇文章主要介紹了C++強(qiáng)制轉(zhuǎn)換與智能指針示例,智能指針(Smart Pointer)是一種抽象的數(shù)據(jù)類(lèi)型。在程序設(shè)計(jì)中,它通常是經(jīng)由類(lèi)模板來(lái)實(shí)現(xiàn),借由模板來(lái)達(dá)成泛型,借由類(lèi)別的析構(gòu)函數(shù)來(lái)達(dá)成自動(dòng)釋放指針?biāo)赶虻拇鎯?chǔ)器或?qū)ο?/div> 2022-11-11
  • C語(yǔ)言實(shí)現(xiàn)掃雷游戲源代碼

    C語(yǔ)言實(shí)現(xiàn)掃雷游戲源代碼

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)掃雷游戲源代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • C++實(shí)現(xiàn)LeetCode(156.二叉樹(shù)的上下顛倒)

    C++實(shí)現(xiàn)LeetCode(156.二叉樹(shù)的上下顛倒)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(156.二叉樹(shù)的上下顛倒),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07

最新評(píng)論

桦川县| 阿拉尔市| 高唐县| 白河县| 美姑县| 内江市| 德清县| 安顺市| 临朐县| 云浮市| 忻州市| 龙门县| 博乐市| 永修县| 岐山县| 大港区| 新野县| 山西省| 金乡县| 会宁县| 大同县| 靖州| 淮北市| 乐山市| 大冶市| 开远市| 稷山县| 台北县| 布尔津县| 蓬莱市| 浑源县| 寻甸| 花垣县| 浮梁县| 峨眉山市| 南安市| 孝昌县| 隆尧县| 沽源县| 南投县| 德江县|