2010-10-21 17 views
18

Mam pytanie dotyczące inicjowania dziedziczonych członków w konstruktorze klasy pochodnej. Przykładowy kod:C++: Inicjalizacja odziedziczonego pola

class A 
    { 
public: 
    int m_int; 
    }; 

class B: public A 
    { 
public: 
    B():m_int(0){} 
    }; 

Ten kod daje mi następujący wynik:

In constructor 'B::B()': Line 10: error: class 'B' does not have any field named 'm_int'

(patrz http://codepad.org/tn1weFFP)

Zgaduję, dlaczego tak się dzieje? m_int powinien być członkiem B, a klasa nadrzędna A powinna już zostać zainicjowana po zainicjowaniu m_int w B (ponieważ konstruktory nadrzędne działają przed inicjacją członka dziedziczonej klasy). Gdzie jest błąd w moim rozumowaniu? Co tak naprawdę dzieje się w tym kodzie?

EDIT: Jestem świadomy innych możliwości zainicjowania tego elementu (konstruktora bazowego lub przypisania w konstruktorze pochodnym), ale chcę zrozumieć, dlaczego jest to nielegalne w sposobie, w jakim go wypróbowuję? Niektóre specyficzne funkcje języka C++ lub takie? Proszę wskazać mi akapit w standardzie C++, jeśli to możliwe.

Odpowiedz

18

Musisz zrobić konstruktor (może to być chronione tak tylko B można go nazwać), który inicjuje m_int tak jak trzeba, a następnie wywołać :A(0) gdzie trzeba :m_int(0)

Można też po prostu ustawić m_int = 0 w ciele konstruktora B. Jest dostępny (jak opisujesz), nie jest dostępny w specjalnej składni konstruktora.

+5

To jest dobra odpowiedź, ale chciałbym tylko dodać wyjaśnienie. Kiedy używasz operatora: mówisz kompilatorowi, że zanim zrobi cokolwiek innego, powinien uruchomić te instrukcje. Zasadniczo ustawiasz zmienną przed uruchomieniem konstruktora macierzystego (lub cokolwiek innego). Dlatego zmienna nie istnieje. : A(), m_int (0) również powinno działać.Domyślnie, jeśli nie używasz:, kompilator uruchomi konstruktor klas podstawowych. Innymi słowy, jeśli nic nie zrobisz, C++ zrobi dla ciebie domyślne rzeczy, jeśli zaczniesz określać rzeczy, zakładasz, że wiesz, co robisz. –

+0

Hmmm ... O ile mi wiadomo, konstruktor klasy nadrzędnej zawsze jest uruchamiany przed innymi inicjalizacjami, więc zmienna 'm_int' już istnieje, gdy próbuję ją zainicjować. To nie powinno być problemem ... – Haspemulator

+0

@ Haspemulator Tak, już istnieje, ale właśnie dlatego otrzymujesz błąd. Jest już domyślnie zainicjowana przez konstruktora A. Nie można ponownie zainicjować zmiennej w konstruktorze B. Możesz zmienić przypisanie, tak jak Ben Jackson stwierdza powyżej ('m_int = 0') i to wszystko w tym momencie. – wheaties

4

Co chcesz to:

class A{ 
public: 
    A() : m_int(0); 
    int m_int; 
}; 

tak że m_int jest inicjowany w prawidłowym miejscu.

Edit:

Z komentarzem powyżej, powodem kompilator narzeka podczas próby zainicjowania zmiennej m_int w B jest to, że już został zainicjowany przez konstruktora A. Oznacza to, że nie można ponownie zainicjować czegoś, a jedynie zmienić przydział. Możesz więc zmienić przypisanie, tak jak to opisano powyżej, lub możesz zainicjować we właściwym miejscu.

4

Aby skonstruować instancję klasy , należy najpierw utworzyć wystąpienie klasy A. Podczas tej inicjacji zostanie zainicjowany m_int. Po tej intializacji wywoływany jest konstruktor b, więc nie można ponownie zainicjować wersji m_int. Jeśli to jest twój cel to można zaimplementować konstruktor A że trwa int a następnie zadzwonić, że w B „s liście inicjalizacji:

class A 
{ 
public: 
    A(int x): m_int(x) {} 
    int m_int; 
}; 

class B: public A 
{ 
public: 
    B(): A(2) {} 
}; 
+0

Czy jest jakiś powód, dla którego nie jest dostępny na liście inicjalizacji? Jestem świadomy innych możliwości zainicjowania tego członka (konstruktora bazowego lub przypisania w konstruktorze pochodnym), ale chcę zrozumieć, dlaczego jest to nielegalne w sposobie, w jaki próbuję? Niektóre specyficzne funkcje języka C++ lub takie? Proszę wskazać mi akapit w standardzie C++, jeśli to możliwe. – Haspemulator

+0

To dwie rzeczy - pochodne klasy najpierw tworzą swoje klasy bazowe, a członkowie są inicjowani w kolejności, w jakiej są zadeklarowani, a nie w kolejności, w jakiej pojawiają się na liście inicjalizacyjnej. Dlatego członkowie bazy są najpierw inicjowani i nie można ich ponownie zainicjować. –

0

dokonać konstruktora w A i użyj b(): A (2) {} insteed z B(): m_int (0) {} jego działanie.

Powiązane problemy