簡體   English   中英

多重繼承

[英]Multiple inheritance

我有2個基類(B1和B2),它們來自公共基類(B),它們有一個公共變量(let: int x;來自基數B),第一個基數x=0 ,第二個基數x=10 (B1,B2構造函數中給出的默認值)。

視覺:

class B
{
    int x;

protected:

    B(int x) : x{x}{}
};

class B1 : public B
{
protected:

    B1() : B(0){}
};

class B2 : public B
{
protected:

    B2() : B(10){}
};

現在,如果我再推導一個類:

class D : virtual public B1, virtual public B2
{
public:

    D() : B1{}, B2{}{}
};

這里只有一個x副本可用於虛擬概念,現在如果我嘗試使用派生類對象訪問x值,x的實例將在O / p( x=0x=10 )中得到,為什么?

為了使用虛擬繼承,必須在B1B2中將基數B聲明為虛擬。 沒有它,你有B的非虛擬繼承。

如果你有非虛擬繼承,那么你在D有兩個B基,所以你不能在D訪問x而不將其限定為B1::xB2::x

如果你有虛擬繼承,那么你只有一個B和一個x ,所以它的兩個賦值( x=0x=10 )將按你執行的順序發生,而后者中的任何一個都將覆蓋該值由前一個設置(與具有兩個賦值的簡單變量x )。

在您的設置中, B實際上並不是虛擬繼承的,因為您必須在B1B2聲明B虛擬繼承(如果預期兩個“分支”預期,它總是必須發生在最低級別)在類繼承層次結構中合並得更高,即

class B1 : virtual public B
{
protected:

    B1() : B(0){}
};

class B2 : virtual public B
{
protected:

    B2() : B(10){}
};

如果這樣做, B初始化將完全不同,因為構建虛擬基類有特殊規則:

在虛擬繼承中,虛擬基類始終由派生程度最高的類初始化。 因此,正如您已經將D的構造函數實現為

D() : B1(), B2(){}

因此,不要顯式調用您的B構造函數,編譯器將假定您要調用B的默認構造函數。 但是你的B類沒有默認的構造函數,所以你會得到一個像這樣的編譯器錯誤:

prog.cpp: In constructor ‘D::D()’:
prog.cpp:31:20: error: no matching function for call to ‘B::B()’
     D() : B1(), B2(){}
                    ^

因此,你必須做類似的事情

class D : public B1, public B2
{
public:

    D() :  B(99), B1(), B2(){}
};

這也解決了你的問題: x的值將是大多數派生類想要的值(在這種情況下為99)。 因此,沒有歧義。

PS:你也看到,你的問題是為什么有最大派生類的虛擬基類構造的特殊規則是有意義的核心。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM