2016-05-14 12 views
7

Poniższy kod działa tylko jeśli odkomentowaniu liniahierarchiczne interfejsy i implementacje

virtual void FuncA() { ImplA::FuncA(); } 

w klasie ImplB, poza otrzymuję błąd kompilatora:

cannot instantiate abstract class ... FuncA(void)' : is abstract

Pytanie to dlaczego się nie dostać implementacja dla FuncA() z odziedziczonego ImplA?

class InterfaceA { 
public: 
    virtual void FuncA()=0; 
}; 

class InterfaceB : public InterfaceA { 
public: 
    virtual void FuncB()=0; 
}; 

class ImplA : public InterfaceA { 
public: 
    virtual void FuncA() { printf("FuncA()\n"); } 
}; 

class ImplB : public ImplA, public InterfaceB { 
public: 
    // virtual void FuncA() { ImplA::FuncA(); } 
    virtual void FuncB() { printf("FuncB()\n"); } 
}; 

{ 
    ImplB *b = new ImplB(); 
    InterfaceA *A= b; 
    A->FuncA(); 
    InterfaceB *B= b; 
    B->FuncB(); 
    B->FuncA(); 
} 
+0

Ponieważ dziedziczy się po interfejsie 'InterfaceB', który jest abstrakcyjny z dwoma czysto wirtualnymi funkcjami, które należy przesłonić. –

+0

klasa ImplA: publiczny interfejsA { publiczny: wirtualna pustka FuncA() {printf ("FuncA() \ n"); } }; – perry

+0

Zauważ, że klasa ImplA została poprawiona, ponieważ poniżej wynik jest taki sam – perry

Odpowiedz

3

pan uderzyć instancję „diamentowej” problem w wielokrotnego dziedziczenia. Będziesz musiał użyć dziedziczenia "wirtualnego" (co oznacza dodanie słowa kluczowego wirtualnie podczas dziedziczenia).

Problem polega na tym, że ImplB ma dwie ścieżki do klasy bazowej InterfaceA. Jednak twoim zamiarem jest, aby interfejsy nie zapewniały żadnej implementacji. Dlatego musisz wskazać to kompilatorowi, aby mógł ujednolicić czyste funkcje wirtualne.

na o wiele lepsze wyjaśnienie: http://www.cprogramming.com/tutorial/virtual_inheritance.html

Mam zmodyfikowany kod, aby dodać wirtualny kiedy dziedziczą z interfejsów. Teraz kompiluje się, nawet z komentarzem linii. Zauważ też, że brakuje ci wirtualnych destruktorów, więc będziesz mieć jeszcze inne problemy. Ten kod kompiluje, nie odrzucając FuncA.

#include <cstdio> 

class InterfaceA { 
public: 
    virtual void FuncA()=0; 
}; 

class InterfaceB : public virtual InterfaceA { 
public: 
    virtual void FuncB()=0; 
}; 

class ImplA : public virtual InterfaceA { 
public: 
    virtual void FuncA() { printf("FuncA()\n"); } 
}; 

class ImplB : public ImplA, public virtual InterfaceB { 
public: 
    // virtual void FuncA() { ImplA::FuncA(); } 
    virtual void FuncB() { printf("FuncB()\n"); } 
}; 

int main() 
{ 
    ImplB *b = new ImplB(); 
    InterfaceA *A= b; 
    A->FuncA(); 
    InterfaceB *B= b; 
    B->FuncB(); 
    B->FuncA(); 
} 
+1

Bardzo wiele podziękowań! Od jakiegoś czasu dręczy mnie to, że jesteś całkowicie przybity. Jestem w twoim długu. – perry

0

Multiple dziedziczenie nie jest „wstawek”

można dziedziczyć z wielu klas, które mają metody o tej samej nazwie, ale to nie czyni ich to samo.

Rzecz, która dziedziczy z klasy wirtualnej, musi implementować czyste wirtualne funkcje swoich rodziców.

Jeśli nazwy metod nie mają określonego zakresu, można uzyskać kombinacje klas nadrzędnych, które wzajemnie się wykluczają, ponieważ dziedziczą implementacje metody o współużytkowanej nazwie.

Jestem nieco zaskoczony, że oddanie using ImplA::FuncA; w ImplB nie rozwiązuje go, choć: https://gcc.godbolt.org/