2015-04-15 21 views
13

Mam hierarchii klasa, która sprowadza się dowirtualnej Dziedziczenie z konstruktora dziedziczenia

class Module { }; 

struct Port { 
    Module& owner; 
    Port(Module& owner) : owner(owner) {} 
}; 

struct InPort : virtual Port { using Port::Port; }; 
struct OutPort : virtual Port { using Port::Port; }; 
struct InOutPort : InPort, OutPort { using Port::Port; }; 

Jak widać, wolałbym stworzyć jakąś podstawową funkcjonalność i dziedziczą go w klasycznym diamentowym wzorem. Ja również chciałbym użyć konstruktora dziedziczenia, aby to tak przyszłościowe, jak to możliwe ...

Jednak this does not work as written down above

prog.cpp: In function 'int main()': 
prog.cpp:14:15: error: use of deleted function 'InOutPort::InOutPort(Module&)' 
    InOutPort p(m); 

Nawet wymiana definicję InOutPort z bardziej wyraźnej wersji is not enough:

struct InOutPort : InPort, OutPort { InOutPort(Module& m) : Port(m), InPort(m), OutPort(m) { } }; 

Zamiast I seem to have to write down everything explicitly for it to work::

struct InPort : virtual Port { InPort(Module& m) : Port(m) { } }; 
struct OutPort : virtual Port { OutPort(Module& m) : Port(m) { } }; 
struct InOutPort : InPort, OutPort { InOutPort(Module& m) : Port(m), InPort(m), OutPort(m) { } }; 

Czy istnieje sposób na połączenie dziedziczenia constuctor z dziedziczeniem wirtualnym, którego nie widzę?
Jeśli nie, jakiej alternatywy używałbyś?
Może konstruktory szablonów wariatów, które doskonale przekazują swoje argumenty do wszystkich baz?

+0

'InPort' i' OutPort' zarówno dziedziczą konstruktor, który wywołuje niezadeklarowany domyślny-konstruktor dla 'Port', ponieważ oba nie są klasą najbardziej pochodną. Program byłby źle sformułowany, gdyby został wywołany. Z tego powodu gcc decyduje się usunąć odpowiednie konstruktory w obu klasach. Clang nie jest i nie da błędu konstruktorom, nawet jeśli podstawy są [zainicjalizowane jawnie] (http://coliru.stacked-crooked.com/a/7c2963ba56e79793). Na marginesie, klang daje również błąd, ponieważ 'Port' nie jest bezpośrednią klasą podstawową' InOutPort' w deklaracji użycia, podczas gdy gcc ją ignoruje. – 0x499602D2

+0

GCC faktycznie usuwa konstruktorów, ponieważ byliby źle sformułowani, ale nie z powodu, który wcześniej przypuszczałem. Wydaje się, że deklaracja użycia [domyślnie odr-używa domyślnego konstruktora] (http://coliru.stacked-crooked.com/a/490c0b5bb17fdc50). Konstruktor default w klasie 'Port' nie jest zadeklarowany, więc usuwa konstruktor wywołujący. To jest błąd. – 0x499602D2

+0

Ponadto dzieje się tak tylko w przypadku wirtualnej klasy bazowej. – 0x499602D2

Odpowiedz

1

Nie wydaje się, że jest jakikolwiek sposób na zrobienie czegoś takiego. W 12,9/8:

... An niejawnie zdefiniowane konstruktor dziedziczenie wykonuje zestaw inicjalizacji klasy, które będą wykonywane przez konstruktora inline użytkownika napisany dla tej klasy z mem-initializer- lista którego tylko mem-inicjator ma MEM-initializer-id, że nazwy klasy bazowej oznaczony w zagnieżdżonej-nAME specyfikatorem z wykorzystaniem-deklaracji i wyrazem liście, jak określono poniżej ...

Innymi słowy, klasa, której konstruktorem dziedziczysz, jest only klasa bazowa, która pobiera argumenty do niej przekazywane. Wszystkie inne klasy bazowe muszą mieć domyślne konstruktory. Ponieważ ukryłeś te domyślne konstruktory w klasach pośrednich przez dziedziczenie konstruktora nadrzędnego, nie możesz wywoływać ich po bezpośrednim przejęciu konstruktora nadrzędnego.

Myślę, że powinieneś być w stanie używać dziedziczonych konstruktorów dla obu klas pośrednich i pisać tylko wersję jawną dla najbardziej pochodnej klasy [Nie widziałem, że już próbowałeś tego - to wygląda na błąd kompilatora z mojego zrozumienie standardu]. Zaktualizuję, jeśli pomyślę o innym lepszym podejściu.

+0

To jest dokładnie to, co sobie wymyśliłem po przekręceniu mojego mózgu z powrotem w dziedziczenie wirtualne - ale dlaczego środkowa wersja (jawne 'InOutPort' z dziedziczeniem' InPort' i 'OutPort') nie działa? Wydaje się, że to błąd w G ++, prawda? –