2012-03-28 16 views
62

Nie rozumiem, dlaczego w poniższym kodzie, gdy zainicjować obiekt typu daughter, domyślny konstruktor grandmother() jest wywoływana?Dlaczego wywoływany jest domyślny konstruktor w dziedziczeniu wirtualnym?

Pomyślałem, że należy wywołać konstruktora grandmother(int) (w celu dostosowania do specyfikacji mojego konstruktora klasy mother), lub ten kod nie powinien się w ogóle kompilować z powodu wirtualnego dziedziczenia.

Tutaj kompilator po cichu wywołuje domyślnego konstruktora, a ja nigdy o to nie prosiłem.

#include <iostream> 

class grandmother { 
public: 
    grandmother() { 
     std::cout << "grandmother (default)" << std::endl; 
    } 
    grandmother(int attr) { 
     std::cout << "grandmother: " << attr << std::endl; 
    } 
}; 

class mother: virtual public grandmother { 
public: 
    mother(int attr) : grandmother(attr) { 
     std::cout << "mother: " << attr << std::endl; 
    } 
}; 

class daughter: virtual public mother { 
public: 
    daughter(int attr) : mother(attr) { 
     std::cout << "daughter: " << attr << std::endl; 
    } 
}; 

int main() { 
    daughter x(0); 
} 
+0

Jaki kompilator (i wersja)? Z jakimi argumentami go skompilowałeś? – orlp

+0

gcc 4.6.3 20120306 (Red Hat 4.6.3-2) na Fedorze 15. Argumentami są: -O0 -g3 -Wall -c -fmessage-length = 0 –

+0

g ++ 4.1.2 ma ten sam problem: http: // codepad.org/L0jBXfSP – orlp

Odpowiedz

66

Podczas korzystania z dziedziczenia wirtualnego konstruktor wirtualnej klasy bazowej jest wywoływany bezpośrednio przez najbardziej pochodny konstruktor klasy. W takim przypadku konstruktor daughter bezpośrednio wywołuje konstruktor grandmother.

Ponieważ nie wywołano jawnie konstruktora grandmother na liście inicjalizacyjnej, zostanie wywołany domyślny konstruktor. Aby wywołać prawidłowy konstruktor, zmień go na:

daugther(int attr) : grandmother(attr), mother(attr) { ... } 

Zobacz także This FAQ entry.

+2

To całkowicie ma sens, dzięki! Wszystkie konstruktory w hierarchii są wywoływane z ostatniej klasy, a nie według ich odpowiedniej klasy potomnej. Nigdy o tym nie myślałem. Specyfikacja C++ może czasami być trudna ... –

+0

Dziękuję! W przypadku dziedziczenia wirtualnego najlepiej jest ręcznie wywołać wszystkich konstruktorów łańcucha. –

+0

Doskonała odpowiedź! Dzięki! –

Powiązane problemy