簡體   English   中英

死亡鑽石和范圍解析運算符(C ++)

[英]Diamond of death and Scope resolution operator (c++)

我有此代碼(鑽石問題):

#include <iostream>
using namespace std;

struct Top
{
    void print() { cout << "Top::print()" << endl; }
};

struct Right : Top 
{
    void print() { cout << "Right::print()" << endl; }
};

struct Left : Top 
{
    void print() { cout << "Left::print()" << endl; }
};

struct Bottom: Right, Left{};

int main()
{
    Bottom b;
    b.Right::Top::print();
}

我想在Top類中調用print()

當我嘗試對其進行編譯時,出現錯誤: 'Top' is an ambiguous base of 'Bottom'此行上'Top' is an ambiguous base of 'Bottom'b.Right::Top::print(); 為什么模棱兩可? 我明確指定要從Right Top Right而不是“ Top Left

我不想知道如何去做,是的,它可以通過引用,虛擬繼承等來完成。我只是想知道為什么b.Right::Top::print(); 曖昧。

為什么模棱兩可? 我明確指定要從Right Top Right而不是“ Top Left

那是您的意圖,但實際上並非如此。 Right::Top::print()明確命名您要調用的成員函數,即&Top::print 但是它沒有指定我們在b哪個子對象上調用該成員函數。 您的代碼在概念上等效於:

auto print = &Bottom::Right::Top::print;  // ok
(b.*print)();                             // error

選擇print的部分是明確的。 bTop的隱式轉換是模棱兩可的。 您必須通過執行以下操作來明確消除前進的方向:

static_cast<Right&>(b).Top::print();

范圍解析運算符是左關聯的(盡管它不允許使用括號)。

因此,雖然您想在B內部引用A::tell ,但id-expression卻在B::A內部tell ,這就是A ,這是模棱兩可的。

解決方法是先強制轉換為明確的基B ,然后再次強制轉換為A

語言咨詢:

[basic.lookup.qual] / 1說,

在將::作用域解析運算符應用於表示其類,名稱空間或枚舉的嵌套名稱說明符之后, ::類或名稱空間成員或枚舉器的名稱

嵌套名稱說明符的相關語法為:

嵌套名稱說明符:

類型名稱 ::

嵌套名稱說明 標識符 ::

因此,第一個嵌套名稱說明符B::並且在其中查找A 然后B::A是表示A的嵌套名稱說明符,並在其中查找tell

顯然,MSVC接受該示例。 它可能具有非標准擴展,可以通過在此類說明符中回溯來解決歧義。

實際上,正如我在Visual Studio 2019上嘗試過的那樣,提供代碼可以正常工作。有兩種解決鑽石問題的方法; -使用范圍解析運算符-將基類繼承為虛擬

通過b.Right::Top::print()調用print函數應正確執行。 但是,您的底層類仍引用了基類(頂層)的兩個對象。

您可以在這里找到更多詳細信息

暫無
暫無

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

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