2012-02-22 16 views
9

Próbuję zdefiniować typy interfejsów w C++ za pomocą klas abstrakcyjnych i zaimplementować je w konkretnych klasach. Problem, na który napotykam, polega na tym, że nie mogę jednocześnie dziedziczyć i interfejsować się z innego interfejsu i dziedziczyć implementację z podstawowej klasy betonu.Implementowanie interfejsów w C++ z odziedziczonymi klasami betonu

Moim celem jest zdefiniowanie hierarchii interfejsów, które mogą dziedziczyć po mniej złożonych interfejsach bazowych. Chcę również móc rozszerzyć implementację interfejsów przez dziedziczenie z konkretnych klas (np. Dziedziczenie z TObjectA w poniższym przykładzie).

To jest to, co mam. Błąd, który otrzymuję, jest "obiektem abstrakcyjnego typu klasy" TObjectB "nie jest dozwolone". Wierzę, że wiem, dlaczego, ponieważ nie zaimplementowałem MethodA() w TObjectB. Ale naprawdę chcę mieć implementację zapewnioną przez klasę podstawową (TObjectA) i nadal mieć hierarchie interfejsów (IInterfaceB dziedziczy z IInterfaceA). Nie chcę również powtarzać wszystkich dziedziczonych metod interfejsu w moich pochodnych klasach konkreacji. Jak mogę to zrobić?

class IInterfaceA 
{ 
public: 
    virtual void MethodA() = 0; 
}; 

class IInterfaceB : IInterfaceA 
{ 
public: 
    virtual void MethodB() = 0; 
}; 

class TObjectA : public IInterfaceA 
{ 
public: 
    void MethodA() { cout << "Method A"; } 
}; 

class TObjectB : public TObjectA, public IInterfaceB 
{ 
public: 
    void MethodB() { cout << "Method B"; } 
}; 

void TestInterfaces() 
{ 
    IInterfaceB* b = new TObjectB(); // error: object of abstract class type "TObjectB" is not allowed 
    b->MethodB(); 
    delete b; 
} 
+2

Potrzebujesz wirtualnych klas bazowych. Na przykład. [patrz tutaj] (http://stackoverflow.com/questions/4605556/when-virtual-inheritance-is-a-good-design/4606206#4606206) –

Odpowiedz

11

w hierarchii klasowej, TObjectB rzeczywiście ma dwie klasy podobiekty IInterfaceA Base: jeden odziedziczony przez IInterfaceB i jeden odziedziczony przez TObjectA. W każdym z nich musi być zaimplementowany kod MethodA().

trzeba dziedziczą z klasy interfejsów wykorzystujących publiczną wirtualny dziedziczenia, co zapewnia nie tylko pojedyncza klasa bazowa podobiekt każdego typu klasy interfejs:

class IInterfaceA 
{ 
public: 
    virtual void MethodA() = 0; 
}; 

class IInterfaceB : public virtual IInterfaceA 
{ 
public: 
    virtual void MethodB() = 0; 
}; 

class TObjectA : public virtual IInterfaceA 
{ 
public: 
    void MethodA() { cout << "Method A"; } 
}; 

class TObjectB : public TObjectA, public virtual IInterfaceB 
{ 
public: 
    void MethodB() { cout << "Method B"; } 
}; 

void TestInterfaces() 
{ 
    TObjectB b_object; 
    IInterfaceB& b = b_object; 
    b.MethodB(); 
} 

czy takie skomplikowane hierarchie klasowe są pożądana jest zupełnie inna sprawa.

+0

Kiedy używam Twojego kodu, otrzymuję następujące ostrzeżenie "Ostrzeżenie:" TObjectB ': dziedziczy "TObjectA :: TObjectA :: MethodA' via dominance". także przy zmianie test korzystania sterty przydzielone obiekty otrzymuję błąd wykonania dochodzenia i wykonanie przystanków: void TestInterfaces() { IInterfaceB * b = new TObjectB(); b-> MetodaB(); kasuj b; } – sysrpl

+0

Twoje klasy interfejsu muszą mieć wirtualne destruktory, jeśli zamierzasz polimorficznie usuwać za ich pomocą obiekty. Co do ostrzeżenia: unikaj złożonych hierarchii dziedziczenia. –

1

Twój problem jest spowodowany przerażającym dziedziczeniem diamentów. Zaimplementowałeś TObjectA::IInterfaceA::MethodA, ale nie IInterfaceB::IInterfaceA::MethodA.

Zalecam, aby IIterfaceA i IIterfaceB były całkowicie niezależne. Jeśli to nie jest możliwe, możesz zajrzeć do wirtualnego dziedziczenia.

Powiązane problemy