我正在學習 C ,在學習虛擬繼承時,我遇到了以下疑問:
class A {
public:
int x;
A() { x = 677; }
A(int a) {
cout << "A con , x= " << a << endl;
x = a;
}
};
class B : public A {
public:
B(int a) : A(a) { }
};
class C :public A {
public:
C(int a) : A(a) { }
};
class D : public B, public C {
public:
D(int a,int b) : B(a),C(b) { }
};
int main()
{
D d(5,6);
cout << d.A::x; //prints 5
}
In linecout << d.A::x;它列印 5。這個呼叫不應該是模棱兩可的,如果不是為什么它列印 5?
uj5u.com熱心網友回復:
d.A::x;確實是模棱兩可。GCC 和 Clang 報告錯誤,只有 MSCV 沒有這樣做:https ://godbolt.org/z/1zhjdE6a8 。
[class.mi] 中有一個注釋,其中有一個多重繼承的例子,說明:
在這樣的格子中,可以使用顯式限定來指定哪個子物件。函式 C :: f 的主體可以參考每個 L 子物件的 next 成員:
void C::f() { A::next = B::next; } // well-formed如果沒有
A?::orB?::限定詞,C?::?f上面的定義會因為歧義([class.member.lookup])而格式錯誤。— 尾注]
這只是一個注釋,因為它遵循[class.member.lookup](閱讀和理解有點人為)如果沒有限定符,成員訪問是不明確的。“格式錯誤”意味著符合標準的編譯器必須發出錯誤或警告。
uj5u.com熱心網友回復:
根據 GCC 和 Clang,這是模棱兩可的,但 MSVC 編譯它(Godbolt)
您可以通過使用虛擬繼承來解決它B,C如果在 D 中只有一個 A 實體有意義,或者A::x如果您需要 D 中 A 的兩個不同實體,您可以指定呼叫必須通過哪個父級訪問。
std::cout << d.B::x; // go through B to its A
std::cout << d.C::x; // go through C to its A
以上在所有 3 個編譯器上編譯都沒有錯誤,因為它是明確的。它指定通過哪個中間類訪問A::x。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/362178.html
