欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

菱形繼承

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

需要注意的是:

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

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

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

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

菱形繼承:

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

缺點(diǎn):

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

解決方法:

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

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

多繼承,呈菱形狀

在這里插入圖片描述

菱形繼承代碼:

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;    問題來了這個(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變量,編譯器無法自主確定需要用哪一個(gè),可以d::A_a 或者 d::B_a這樣使用;

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

虛繼承 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,這個(gè)2是D類成員通過繼承,使得d自己獨(dú)有且只有一份的 A::_a成員變量;
    return 0;
}

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

在這里插入圖片描述

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

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

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

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

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

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

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

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

感悟

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

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

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

在這里插入圖片描述

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

在這里插入圖片描述

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

相關(guān)文章

  • opencv3/C++ 離散余弦變換DCT方式

    opencv3/C++ 離散余弦變換DCT方式

    今天小編就為大家分享一篇opencv3/C++ 離散余弦變換DCT方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • QT使用canon sdk拍照并保存到本機(jī)的方法示例

    QT使用canon sdk拍照并保存到本機(jī)的方法示例

    這篇文章主要介紹了QT使用canon sdk拍照并保存到本機(jī)的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 基于list循環(huán)刪除元素,迭代器失效的問題詳解

    基于list循環(huán)刪除元素,迭代器失效的問題詳解

    下面小編就為大家?guī)硪黄趌ist循環(huán)刪除元素,迭代器失效的問題詳解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • 深入理解數(shù)組指針與指針數(shù)組的區(qū)別

    深入理解數(shù)組指針與指針數(shù)組的區(qū)別

    本篇文章是對(duì)數(shù)組指針與指針數(shù)組的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 使用C語言求解撲克牌的順子及n個(gè)骰子的點(diǎn)數(shù)問題

    使用C語言求解撲克牌的順子及n個(gè)骰子的點(diǎn)數(shù)問題

    這篇文章主要介紹了使用C語言求解撲克牌的順子及n個(gè)骰子的點(diǎn)數(shù)問題的方法,解答實(shí)例主要為了突出解題的算法,需要的朋友可以參考下
    2016-03-03
  • C語言實(shí)現(xiàn)三子棋游戲附注釋

    C語言實(shí)現(xiàn)三子棋游戲附注釋

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)三子棋游戲附注釋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C++利用GPAC實(shí)現(xiàn)生成MP4文件的示例代碼

    C++利用GPAC實(shí)現(xiàn)生成MP4文件的示例代碼

    GPAC主要針對(duì)學(xué)生和內(nèi)容創(chuàng)作者,代表了一個(gè)跨平臺(tái)的多媒體框架,開發(fā)人員可以使用它在?LGPL?許可下制作開源媒體。本文就來用GPAC實(shí)現(xiàn)生成MP4文件,感興趣的可以了解一下
    2023-02-02
  • 深入學(xué)習(xí)C語言中常見的八大排序

    深入學(xué)習(xí)C語言中常見的八大排序

    排序編程中非?;A(chǔ)的的理論方法,雖然排序的方法多,但是理解起來并不難,它是最基本的,初學(xué)者一定要掌握的東西。本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值
    2021-11-11
  • C語言超詳細(xì)講解排序算法下篇

    C語言超詳細(xì)講解排序算法下篇

    今天我們主要難點(diǎn)有快速排序和歸并排序,會(huì)簡(jiǎn)單涉及到二叉樹相關(guān)知識(shí),相對(duì)來說比較抽象!所以如果有看不懂或者不明白的地方可以看看我之前的詳解二叉樹
    2022-04-04
  • C++虛函數(shù)表的原理與使用解析

    C++虛函數(shù)表的原理與使用解析

    對(duì)C++?了解的人都應(yīng)該知道虛函數(shù)(Virtual?Function)是通過一張?zhí)摵瘮?shù)表(Virtual?Table)來實(shí)現(xiàn)的。簡(jiǎn)稱為V-Table。本文就將詳細(xì)講講虛函數(shù)表的原理與使用,需要的可以參考一下
    2022-04-04

最新評(píng)論