簡體   English   中英

多態如何涉及多重繼承?

[英]How polymorphism works involving multiple inheritance?

我正在研究與多重繼承相關的主題。 我提出了以下代碼,但無法完全弄清其背后的機制:

struct root
{
    virtual void vfunction(){ /* root version */ }
};

struct mid1:public root
{
    virtual void vfunction(){ /* mid1 version */ }
};

struct mid2:public root
{
    virtual void vfunction(){ /* mid2 version */ }
};

struct inheritMulti:public mid1, public mid2
{
    void ambiguityMethod(){
        vfunction();    // error: ambiguous
    }
    void method1(){
        mid1& t = *this;
        t.vfunction();
    }
    void method2(){
        mid2& t = *this;
        t.vfunction();
    }
};

顯然, ambiguityMethod是一個錯誤。 然而,函數調用這兩個method1method2搞糊塗了。 它們也是虛擬函數調用,並且t實際上是inheritMulti類型。 所以他們應該叫inheritMulti版本vfunction ,但由於inheritMulti沒有它自己的版本,我不知道會發生什么。 結果表明method1調用調用了mid1版本,而method2調用調用了mid2版本。 它是未定義的東西,只發生在我的編譯器上嗎? 如果沒有,為什么它會這樣工作? vtable如何處理這種情況? 謝謝!


首先感謝您的幫助。 我自己搜索過有關主題的文章,所以,我知道“鑽石問題”。 但我認為我的問題與此不同。 我最關心的是“虛函數調用”的行為是否method1method2明確定義或標准定義的。 在編譯器中,它的行為類似於我上面提到的,但是標准所承諾的行為是嗎? 如果定義明確,為什么要分別調用mid1和'mid2'版本? (直覺的想法是調用tinheritMulti版本,因為t的類型實際上是inheritMulti )而且,大多數編譯器如何處理這種情況? 這是奇怪的是,在虛擬函數調用method1method2調用不同的功能。 再次感謝!

虛擬關鍵字根本不在此處播放。

當兩個類的函數具有相同的名稱,而第三個類都從它們繼承時,則在使用范圍運算符::調用該函數時,需要手動指定要引用的基類。

 void ambiguityMethod(){
        mid1::vfunction();
    }

要么

 void ambiguityMethod(){
        mid2::vfunction();
    }

要么

 void ambiguityMethod(){
        root::vfunction();
    }

與t:(警告:奇怪的語法!)
t.mid1::vfunction();

您還可以重寫此函數並調用一些基類函數,從而僅指定一次調用哪個函數:

void inheritMulti::vfunction() override {
  return mid1::vfunction();
}

調用vfunction ,編譯器將搜索具有相同簽名的最近的函數,並將調用此函數,而該函數又將調用mid1函數

您的代碼描述了多重繼承中的“鑽石問題”(對於vfunction )眾所周知的問題。 對於method1method2一切都很好,因為你正在mid1mid2從對象this ,並呼吁vfunction從他們的命名空間。

void method1(){
    mid1& t = *this;
    t.vfunction();
}

在這里,您要調用vfunction ,該函數未在inheritMulti定義,因此它將搜索vfunction的最接近定義,該定義存在於mid1 請參閱層次結構。

根-> Mid1-> inheritMulti

根目錄->中2->繼承多

同樣的情況

`void method2(){
    mid2& t = *this;
    t.vfunction();
}

在這里,在mid2中也找到了最接近的定義,因此得到了輸出。 這些調用不是模棱兩可的,因為兩個結構都在其中創建了自己的vfunction副本。

inheritMulti將有兩個名為mid1mid2的子對象,並且這些子對象中的每一個都維護自己的vtable指針。 雖然您可能會認為

mid1& t1 = *this;

mid2& t2 = *this;

t1和t2都相同,但是請嘗試這樣做...

bool same = ((void*)t1) == ((void*)t2);  // Result false!

因為編譯器在后面生成一些代碼來調整指針以指向正確的對象。

暫無
暫無

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

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