2011-06-27 20 views
7
class A { 
    public: 
     void fa() { 
     } 
    }; 

class B : public A{ 
public: 
    void fb() { 
    } 
}; 

class C : public A, public B { 
public: 
    void fc() { 
     //call A::fa(), not B::A::fa(); 
    } 
}; 

Jak zadzwonić pod numer A::fa() z funkcji C::fc().Poleć członków klasy podstawowej z klasy pochodnej

GCC ostrzega z direct base A inaccessible in C due to ambiguity, czy to oznacza, że ​​nie ma bezpośredniego sposobu na odesłanie członków klasy podstawowej?

+0

W swoim obecnym kodem 'klasy B' nie dziedziczyć klasy' A'. Czy można umieścić zaktualizowanego kodu? – iammilind

+0

Moja pomyłka :) , teraz jest naprawiony – MKo

+1

Czy chcesz mieć jeden podobiekt klasy bazowej 'A' dla' C' lub dwóch podobiektów klasy bazowej 'A' (jeden z' C' wywodzący się z 'A' i jeden z' B' wywodzący się z 'A')? W tej chwili masz dwa, które mogą, ale nie muszą być twoją intencją. –

Odpowiedz

0

Można użyć virtual dziedziczenia do przezwyciężenia tego problemu:

class B : virtual public A { 

Teraz można użyć A::fa() prostu w dziecku class C.

void fc() 
{ 
    fa(); 
} 

Jednak generalnie nie widzę żadnego praktycznego potrzebę dziedziczenia class A ponownie do class C, gdy B jest już public sojusznikiem dziedziczenie A. Tak więc, w przypadku, możesz zrobić to proste:

class C : public B { 

Edit:

Jeśli chcesz 2 instancje dla A. wówczas bezpośredni instancja który masz zamiar może być wykonany jako przedmiot C:

class C : public B { 
    A obj; 

Ponieważ posiadające bezpośrednio dziedziczona A nie będą używane w każdym razie. Nie można zadeklarować żadnego wskaźnika ani odnośnika do niego w zakresie C.

+0

To nie jest praktyczne, chcę tylko wiedzieć, czy istnieje sposób, aby to zrobić? Przy okazji, w przypadku wirtualnego dziedziczenia, będzie jedna klasa bazowa A i nie będzie żadnych niejasności. – MKo

+0

@MKo, już wspomniałem w mojej zredagowanej odpowiedzi. W twoim przypadku nie musisz dziedziczyć 'A' w' C'. Również może okazać się zła konstrukcja na dłuższą metę. – iammilind

1

Właśnie skompilowałem kod na codepad.org, wprowadzenie A::fa() wystarczy, aby zadzwonić do fa() z funkcji C::fc().

void fc() { 
     A::fa(); 
    } 

Poniżej znajduje się link do kodu pocztowego z kodem.

http://codepad.org/NMFTFRnt

+0

Nie wiem, jakiego używa codepad kompilatora, ale clang 3.0/133044 i g ++ 4.5.1 odrzucają to. –

+0

@James McNellis: tak, to bardziej dotyczy ** problemu z kompilatorem ** nie z samym językiem. – Jhaliya

+0

Kompiluje się, ponieważ 'B' nie pochodzi z' A' w kodzie. –

8

Jedną z opcji byłoby utworzyć klasy skrótową, które można wykorzystać do odlewania do prawej klasy bazowej podobiektu:

struct A { 
    void fa() { } 
}; 

struct B : A { 
    void fb() { } 
}; 

// Use a stub class that we can cast through: 
struct A_ : A { }; 

struct C : A_, B { 
    void fc() { 
     implicit_cast<A_&>(*this).fa(); 
    } 
}; 

Gdzie implicit_cast jest zdefiniowany jako:

template <typename T> struct identity { typedef T type; } 

template <typename T> 
T implicit_cast(typename identity<T>::type& x) { return x; } 
+0

Przyznaję, że Jestem zaskoczony tym pytaniem i jestem bardzo zainteresowany, czy istnieje sposób, aby to zrobić bez wstrzykiwania klasy pośredniej do siatki. –

+0

Korzystanie z kodu pośredniczącego to miłe obejście problemu, nie sądzę, że istnieje sposób na osiągnięcie tego zachowania bez takiej sztuczki. To jest ograniczenie języka, którego nigdy nie brałem pod uwagę! –

+0

Dlaczego używasz 'implicit_cast' zamiast' static_cast'? Znajduję wpis SO odpowiadający na moje pytanie, ale możesz dodać trochę wyjaśnienia lub link do niektórych informacji na ten temat. –

0

Nie sądzę, że możesz zrobić to, co chcesz. Występuje tu niejasność: kiedy mówisz A::fa(), nadal nie informuje kompilatora, który obiekt powinien użyć. Nie ma żadnego sposobu uzyskania dostępu do klasy A. Tak mówi ostrzeżenie.

Wydaje się to jednak dziwnie dziwną konstrukcją. Powinno się używać dziedziczenia publicznego dla relacji is-a. Mówisz, że C jest-dwa razy więcej niż -? To nie ma sensu. Sugeruje to, że jest to sztuczny przykład, który nigdy nie pojawiłby się w praktyce, lub należy ponownie rozważyć ten projekt.

5

Właśnie znalazłem następujące informacje z normy ISO C++ 2003 (10.1.3)

A class shall not be specified as a direct base class of a derived class more than once. [Note: a class can be 
an indirect base class more than once and can be a direct and an indirect base class. There are limited 
things that can be done with such a class. The non-static data members and member functions of the direct 
base class cannot be referred to in the scope of the derived class. However, the static members, enumerations 
and types can be unambiguously referred to. 

To znaczy nie ma bezpośredni sposób :(

Powiązane problemy