Dlaczego nie mogę tego zrobić?
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
c++
inheritance
amrhassan
źródło
źródło
Odpowiedzi:
Nie można zainicjować
a
ib
naB
ponieważ nie są członkamiB
. Są członkamiA
, więc tylkoA
mogą je inicjalizować. Możesz je upublicznić, a następnie wykonać przypisanieB
, ale nie jest to zalecana opcja, ponieważ zniszczyłaby hermetyzację. Zamiast tego utwórz konstruktor w programie,A
aby umożliwićB
(lub dowolną podklasęA
) ich zainicjowanie:źródło
a
ib
naB::B()
ponieważ są prywatne. Nie możesz ich zainicjować, ponieważ nie są członkamiclass B
. Jeśli upubliczniłeś je lub chroniłeś, możesz przypisać je w treściB::B()
.a
ib
...” i zmieniłem to na „Nie możesz zainicjować ...” bez upewnienia się, że reszta zdania ma sens. Edytowano post.Pomijając fakt, że są
private
, ponieważ są członkamia
ib
są członkamiA
, mają być inicjowane przezA
konstruktory, a nie przez konstruktory innej klasy (pochodne lub nie).Próbować:
źródło
Jakoś nikt nie wymienił najprostszego sposobu:
Nie możesz uzyskać dostępu do podstawowych elementów członkowskich na liście inicjalizatora, ale sam konstruktor, podobnie jak każda inna metoda członkowska, może uzyskać dostęp
public
iprotected
elementy członkowskie klasy bazowej.źródło
B
przydzieleniu instancji programu zostanie ona najpierw zainicjowana domyślnie , a następnie zostanie przypisana wewnątrzB
konstruktora. Ale myślę też, że kompilator nadal może to zoptymalizować.class A
nie możemy polegaća
ib
jest inicjowany. Każda implementacjaclass C : public A
, na przykład, może zapomnieć o wywołaniua=0;
i pozostawića
niezainicjowaną.class A { int a = 0;};
) lub w konstruktorze klasy bazowej. Podklasy nadal mogą w razie potrzeby ponownie zainicjować je w swoim konstruktorze.Jest to działający przykład na wypadek, gdybyś chciał zainicjować składowe danych klasy bazowej obecne w obiekcie klasy pochodnej, podczas gdy chcesz przekazać te wartości za pośrednictwem wywołania konstruktora klasy pochodnej.
źródło
Chociaż jest to przydatne w rzadkich przypadkach (gdyby tak nie było, język pozwoliłby na to bezpośrednio), spójrz na idiom Base from Member . To nie jest rozwiązanie wolne od kodu, musiałbyś dodać dodatkową warstwę dziedziczenia, ale wykonuje to zadanie. Aby uniknąć standardowego kodu, możesz użyć implementacji boost
źródło
Dlaczego nie możesz tego zrobić? Ponieważ język nie pozwala na inicjalizację elementów członkowskich klasy bazowej na liście inicjatorów klasy pochodnej.
Jak możesz to zrobić? Lubię to:
źródło
Jeśli nie określisz widoczności dla członka klasy, domyślnie będzie to „prywatna”. Powinieneś uczynić swoich członków prywatnymi lub chronionymi, jeśli chcesz uzyskać do nich dostęp w podklasie.
źródło
Klasy agregujące, takie jak A w Twoim przykładzie (*), muszą mieć swoje elementy członkowskie jako publiczne i nie mogą mieć konstruktorów zdefiniowanych przez użytkownika. Są one inicjowane z listą inicjalizacyjną, np.
A a {0,0};
Lub w twoim przypadkuB() : A({0,0}){}
. Elementy członkowskie podstawowej klasy zagregowanej nie mogą być indywidualnie inicjowane w konstruktorze klasy pochodnej.(*) Mówiąc dokładniej, jak słusznie wspomniano, oryginał
class A
nie jest agregatem ze względu na prywatne niestatyczne elementy członkowskieźródło