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

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

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

菱形繼承

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

需要注意的是:

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

2.上面的不可訪問是指派生類對象不管是在類里還是類外都不能不訪問

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

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

菱形繼承:

  • 兩個子類同時繼承一個父類,而又有子類同時繼承這兩個子類

缺點:

  • 導致數(shù)據(jù)冗余和二義性的問題

解決方法:

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

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

多繼承,呈菱形狀

在這里插入圖片描述

菱形繼承代碼:

class A 
{
public:
    A() {}
    int _a ;
};
class B :public A 
{
public:
    //會存在父的int a;
    B() {}
    int _b ;
};
class C :public A 
{
public:
   //會存在父的int a;
    C() {}
    int _c ;
};
class D :public B,public C 
{
public:
   //會存在父的int a;    問題來了這個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.a具有二義性
    return 0;
}

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

在這里插入圖片描述

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

應對方案

虛繼承 vitrual

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

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;//沒問題,輸出2,這個2是D類成員通過繼承,使得d自己獨有且只有一份的 A::_a成員變量;
    return 0;
}

解決二義性變量內(nèi)存布局–虛基表

在這里插入圖片描述

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

這個兩個地址就叫虛基表指針;

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

這樣我們直接使用d::a的時候,因為獨有一份,也不會出現(xiàn)數(shù)據(jù)二義性的問題了;

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

其次,虛基表的指針,經(jīng)過測試,也是某個多繼承派生類的多對象共用的;

eg: D d1,d2; 其中d1,d2兩個對象 上圖的這兩張?zhí)摶碇羔樖且粯拥?,原因很簡單,D類類型都一樣,那么某個位置起,到另一個相對位置偏移量肯定是固定的!

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

感悟

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

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

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

在這里插入圖片描述

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

在這里插入圖片描述

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

相關(guān)文章

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

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

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

    使用C語言實現(xiàn)學生成績管理系統(tǒng)

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

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

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

    C語言詳細講解位運算符的使用

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

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

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

    使用C++繪制GDI位圖的基本編寫實例

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

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

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

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

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

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

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

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

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

最新評論

宝山区| 景德镇市| 江门市| 龙泉市| 新余市| 津南区| 靖安县| 门源| 万源市| 太白县| 渝中区| 安乡县| 镇康县| 通州区| 商城县| 习水县| 那曲县| 岳池县| 海林市| 湛江市| 威海市| 琼结县| 霍州市| 信阳市| 芮城县| 洛南县| 澜沧| 灵台县| 盘锦市| 安多县| 铅山县| 山东省| 黄大仙区| 新兴县| 马龙县| 邵武市| 屏南县| 固始县| 安龙县| 安徽省| 蒙自县|