2014-09-20 21 views
8

Próbuję uzyskać dostęp do zmiennej członkowskiej x w struct Top przy użyciu obiektu.Podczas korzystania z dziedziczenia wielokrotnego, dlaczego ta kwalifikowana nazwa jest niejednoznaczna?

Kod jest następujący:

#include <cstdio> 

struct Top 
{ 
public: 
    int x = 1; 
}; 

struct Left : public Top 
{ 
    int x = 2; 
}; 

struct Right : public Top 
{ 
    int x = 3; 
}; 

struct Bottom : public Left, public Right 
{ 
    int x = 4; 
}; 

int main() 
{ 
    Bottom b; 
    std::printf("value: %d\n", b.Left::Top::x); 
    return 0; 
} 

To daje następujący błąd przy użyciu gcc 4.8:

main.cpp: In function 'int main()': 
main.cpp:27:45: error: 'Top' is an ambiguous base of 'Bottom' 
std::printf("value: %d\n", b.Left::Top::x); 
             ^

Jak to jest wieloznaczne i jak mam do niego dostęp za pomocą kwalifikowanej nazwy?

+0

Zarówno 'Left' jak i' Right' dziedziczą z 'Top', a oba mają element danych' x'. Stąd niejednoznaczność. –

+0

jest niejednoznaczny, ponieważ masz 'Left' i' Right' jako podklasy 'Top', z których każda definiuje' x'. Jeśli podklasa "Bottom" obie te, to nie można określić "x" z "Left" lub "Right". Dla rekordu twoje kwalifikowane nazwisko nie jest niejednoznaczne, twoja struktura dziedziczenia jest. –

+3

Wiem, że dostęp do niewykwalifikowanego członka wielokrotnego diamentu spadkowego jest niejednoznaczny. Pytanie tutaj brzmi: dlaczego wciąż jest niejednoznaczne, czy w pełni je kwalifikuję. Na przykład, jeśli statycznie rzucam najpierw na lewo, a potem na górę, mogę uzyskać dostęp do prawidłowej wartości x. Dlaczego nie działa dla nazw kwalifikowanych? – anoncoder

Odpowiedz

4

Problemem jest to, że C++ nie ma możliwości bezpośredniego wyrażania pojęcia „wielokrotnego poziomie” członków klasy, takich jak „członka x z Top podobiektu z Left”. Co oznacza Left::Top::x oznacza "członek x w typie oznaczonym przez Left::Top" - a typ oznaczony przez Left::Top to dokładnie Top.

Dlatego można napisać dziwne rzeczy jak

int Left::* ptr = &Right::Top::x; 

ponieważ prawa strona ręka = jest dokładnie równoważne &Top::x oraz wskaźnik do bazy-klasa-członek jest niejawnie przekształcić w element klasy wskaźnik do klasy pochodnej. (Wynik tej konwersji nadal odnosi się do elementu w podobieństwie klasy bazowej klasy pochodnej).

Aby ujednoznacznić się, możesz zrobić coś podobnego do linii static_cast<Left &>(b).Top::x lub użyć wskaźnika do członka - dane int Left::* ptr = &Top::x;, b.*ptr będzie odnosić się do x w podobiekcie TopLeft podporządkowania b.

Powiązane problemy