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

詳解C++中菱形繼承的原理與解決方法

 更新時(shí)間:2023年02月01日 11:44:26   作者:謎一樣的男人1  
C++中的菱形繼承是多繼承的一種特殊情況,本文將通過海里帶大家了解一下菱形繼承形成的原因以及想應(yīng)的解決方法,感興趣的可以了解一下

菱形繼承形成原因

多繼承,呈菱形狀

菱形繼承代碼:

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ì)象; 耦合度高

// Car和BMW Car和Benz構(gòu)成is-a的關(guān)系
class Car{
    protected:
    string _colour ="白色"; // 顏色
    
    string _num ="陜ABITB";// 車牌號(hào)
};

class BMW:public Car{
    public:
    void Drive() {cout <<"好開-操控"<< end1;}
    };
    
    class Benz : public Car{
        public:
        void Drive() {cout <<"好坐-舒適"<< endl;}
        };

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

// Tire和Car構(gòu)成has-a的關(guān)系

class Tiref{
    protected:
    string _brand = "Michelin";// 品牌
    size_t size = 17;// 尺寸
    
};
class Car{
    protected:
    string _colour ="白色";// 顏色
    string _num ="陜ABITO";// 車牌號(hào)
    Tire _t;// 輪胎

};

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

相關(guān)文章

  • C語言實(shí)現(xiàn)abs和fabs絕對(duì)值

    C語言實(shí)現(xiàn)abs和fabs絕對(duì)值

    這篇文章主要介紹了C語言實(shí)現(xiàn)abs和fabs絕對(duì)值,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • C語言簡(jiǎn)明講解變量的屬性

    C語言簡(jiǎn)明講解變量的屬性

    我們知道以在?C?語言中的變量有自己的屬性,只要在定義變量的時(shí)候加上“屬性”關(guān)鍵字即可?!皩傩浴标P(guān)鍵字指明變量的特有意義,但是?register?關(guān)鍵字只是請(qǐng)求寄存器變量,所以不一定會(huì)成功
    2022-04-04
  • C語言中scanf函數(shù)的原樣輸入的坑及解決

    C語言中scanf函數(shù)的原樣輸入的坑及解決

    這篇文章主要介紹了C語言中scanf函數(shù)的原樣輸入的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 基于C語言實(shí)現(xiàn)的aes256加密算法示例

    基于C語言實(shí)現(xiàn)的aes256加密算法示例

    這篇文章主要介紹了基于C語言實(shí)現(xiàn)的aes256加密算法,結(jié)合具體實(shí)例形式詳細(xì)分析了C語言實(shí)現(xiàn)的aes256加密算法實(shí)現(xiàn)步驟與使用技巧,需要的朋友可以參考下
    2017-02-02
  • C語言字符串操作總結(jié)大全(超詳細(xì))

    C語言字符串操作總結(jié)大全(超詳細(xì))

    本篇文章是對(duì)C語言字符串操作進(jìn)行了詳細(xì)的總結(jié)分析,需要的朋友參考下
    2013-05-05
  • C++實(shí)現(xiàn)LeetCode(101.判斷對(duì)稱樹)

    C++實(shí)現(xiàn)LeetCode(101.判斷對(duì)稱樹)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(101.判斷對(duì)稱樹),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 詳解C語言中的預(yù)處理命令

    詳解C語言中的預(yù)處理命令

    初學(xué)C語言的時(shí)候,我們會(huì)在開頭寫下一句話,#include<stdio.h>,這就是預(yù)處理命令,下面我們通過這篇文章來了解一下,感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-12-12
  • opencv實(shí)現(xiàn)定時(shí)錄像功能

    opencv實(shí)現(xiàn)定時(shí)錄像功能

    這篇文章主要為大家詳細(xì)介紹了opencv實(shí)現(xiàn)定時(shí)錄像功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Qt跨平臺(tái)窗口選擇功能的實(shí)現(xiàn)過程

    Qt跨平臺(tái)窗口選擇功能的實(shí)現(xiàn)過程

    很多時(shí)候?yàn)榱朔奖丬浖氖褂?我們需要讓編寫的界面程序顯示在最上層,這時(shí)候就需要對(duì)窗口屬性進(jìn)行調(diào)整,下面這篇文章主要給大家介紹了關(guān)于Qt跨平臺(tái)窗口選擇功能的實(shí)現(xiàn)過程,需要的朋友可以參考下
    2022-12-12
  • C語言利用棧實(shí)現(xiàn)對(duì)后綴表達(dá)式的求解

    C語言利用棧實(shí)現(xiàn)對(duì)后綴表達(dá)式的求解

    這篇文章主要為大家詳細(xì)介紹了C語言利用棧實(shí)現(xiàn)對(duì)后綴表達(dá)式的求解,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04

最新評(píng)論