2013-08-23 14 views
8

próbowałem ten kod:C++ dziedziczyć z wielu klas bazowych o tej samej nazwie wirtualnego funkcji

class A 
{ 
    virtual void foo() = 0; 
}; 

class B 
{ 
    virtual void foo() = 0; 
}; 

class C : public A, public B 
{ 
    //virtual void A::foo(){} 
    //virtual void B::foo(){} 

    virtual void A::foo(); 
    virtual void B::foo(); 
}; 

void C::A::foo(){} 
void C::B::foo(){} 

int main() 
{ 
    C c; 
    return 0; 
} 

Jest OK podczas korzystania z skomentował udział, ale gdy próbuję napisać definicje poza deklaracją klasy, kompilator zgłasza błędy. Używam kompilatora MSVC11, czy ktoś wie, jak to napisać? Potrzebuję przenieść kod do pliku cpp.

Dziękuję ~~

+1

skomentowane część jest również nie działa w gcc. –

+2

To nie ma żadnego sensu. Powinno to być po prostu 'virtual void foo();' i just * once *. –

+0

Jak chcesz _use_ 'A',' B' i 'C'? Istnieje wiele możliwości: [przykład 1] (http://ideone.com/KlVTgv), [przykład 2] (http: // ideone.com/R2SyTz), ... (prawdopodobnie określają więcej funkcji, niż to konieczne) –

Odpowiedz

4

Masz tylko jedną funkcję wirtualną foo:

class A { 
    virtual void foo() = 0; 
}; 

class B { 
    virtual void foo() = 0; 
}; 

class C : public A, public B { 
    virtual void foo(); 

}; 

void C::foo(){} 
void C::A::foo(){} 
void C::B::foo(){}; 

int main() { 
    C c; 
    return 0; 
} 
+3

* Tylko uwaga: * Definicje 'void C :: A :: foo() {}' i 'void C :: B :: foo() {}' zapewniają definicje czystych funkcji wirtualnych 'A :: foo 'i' B :: foo', odpowiednio (i nie są wymagane). – dyp

+0

jak powiedzieć ** dyp **: 'void C :: foo() {cout <<" C "<< endl;} void C :: A :: foo() {cout <<" A "<< endl ;} void C :: B :: foo() {cout << "B" << endl;}; int main() { C c; c.foo(); ((A &) c) .foo(); ((B &) c) .foo(); return 0; } '** zawsze wypisz 'C' ** – biv

+0

@dyp Po prostu ciekawy dlaczego jest prawnie używać składni' void C :: A :: foo() {} ', aby zapewnić definicję' A :: foo() ', Jakieś korzyści z używania tego rodzaju składni zamiast bezpośredniego nadpisywania 'A :: for() {}'? Wydaje mi się to bardzo kłopotliwe, a jeśli "A" jest wewnętrzną klasą? Skompilowałem ten kod i byłem zaskoczony, że to legalne. – Dreamer

15

funkcja zastępuje funkcję wirtualną klasę bazową na podstawie nazwy i parametrów typów (patrz niżej) . W związku z tym klasa C ma jedną wirtualną funkcję, jedną odziedziczoną po każdym A i B. Ale to funkcja void C::foo() zastępuje zarówno:

[class.virtual]/2

Jeżeli wirtualne funkcja element vf deklaruje klasą Base w klasie Derived, pochodzący, bezpośrednio lub pośrednio, z Base , funkcja członkowska vf o tej samej nazwie, listę parametrów typu, kwalifikację cv i kwalifikację ref (lub jej brak) jako Base::vf jest zadeklarowana, następnie Derived::vf jest również wirtualna (niezależnie od tego, czy jest to deklaracja, czy nie). ed) i to przesłaniaBase::vf.

Jak już podano w komentarzach, [dcl.meaning]/1 zabrania zastosowanie kwalifikowanej ID w zgłoszeniu o (użytkownik) Funkcja:

Gdy declarator-id jest kwalifikowana, deklaracja odnosi się do wcześniej zadeklarowanej członek klasy lub przestrzeni nazw, do których odnosi się kwalifikator [...]”

Dlatego każdy virtual void X::foo(); jest illeg al jako deklaracja wewnątrz C.

Kod

class C : public A, public B 
{ 
    virtual void foo(); 
}; 

jest jedynym sposobem AFAIK przesłonić foo, i zastąpi on zarówno A::foo i B::foo. Nie ma sposobu, aby mieć dwa różne nadpisania dla A::foo i B::foo z różnych zachowań innych niż wprowadzając kolejną warstwę dziedziczenia:

#include <iostream> 

struct A 
{ 
    virtual void foo() = 0; 
}; 

struct B 
{ 
    virtual void foo() = 0; 
}; 

struct CA : A 
{ 
    virtual void foo() { std::cout << "A" << std::endl; } 
}; 

struct CB : B 
{ 
    virtual void foo() { std::cout << "B" << std::endl; } 
}; 

struct C : CA, CB {}; 

int main() { 
    C c; 
    //c.foo(); // ambiguous 

    A& a = c; 
    a.foo(); 

    B& b = c; 
    b.foo(); 
} 
Powiązane problemy