Dlaczego nie mogę tego zrobić?
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
Dlaczego nie mogę tego zrobić?
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
Odpowiedzi:
Nie można zainicjować a
i b
na B
ponieważ nie są członkami B
. Są członkami A
, więc tylko A
mogą je inicjalizować. Możesz je upublicznić, a następnie wykonać przypisanie B
, 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:
class A
{
protected:
A(int a, int b) : a(a), b(b) {} // Accessible to derived classes
// Change "protected" to "public" to allow others to instantiate A.
private:
int a, b; // Keep these variables private in A
};
class B : public A
{
public:
B() : A(0, 0) // Calls A's constructor, initializing a and b in A to 0.
{
}
};
a
i b
na B::B()
ponieważ są prywatne. Nie możesz ich zainicjować, ponieważ nie są członkami class B
. Jeśli upubliczniłeś je lub chroniłeś, możesz przypisać je w treści B::B()
.
a
i b
...” 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łonkami a
i b
są członkami A
, mają być inicjowane przez A
konstruktory, a nie przez konstruktory innej klasy (pochodne lub nie).
Próbować:
class A
{
int a, b;
protected: // or public:
A(int a, int b): a(a), b(b) {}
};
class B : public A
{
B() : A(0, 0) {}
};
Jakoś nikt nie wymienił najprostszego sposobu:
class A
{
public:
int a, b;
};
class B : public A
{
B()
{
a = 0;
b = 0;
}
};
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
i protected
elementy członkowskie klasy bazowej.
B
przydzieleniu instancji programu zostanie ona najpierw zainicjowana domyślnie , a następnie zostanie przypisana wewnątrz B
konstruktora. Ale myślę też, że kompilator nadal może to zoptymalizować.
class A
nie możemy polegać a
i b
jest inicjowany. Każda implementacja class C : public A
, na przykład, może zapomnieć o wywołaniu a=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.
# include<stdio.h>
# include<iostream>
# include<conio.h>
using namespace std;
class Base{
public:
Base(int i, float f, double d): i(i), f(f), d(d)
{
}
virtual void Show()=0;
protected:
int i;
float f;
double d;
};
class Derived: public Base{
public:
Derived(int i, float f, double d): Base( i, f, d)
{
}
void Show()
{
cout<< "int i = "<<i<<endl<<"float f = "<<f<<endl <<"double d = "<<d<<endl;
}
};
int main(){
Base * b = new Derived(10, 1.2, 3.89);
b->Show();
return 0;
}
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.
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
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:
class A
{
public:
A(int a, int b) : a_(a), b_(b) {};
int a_, b_;
};
class B : public A
{
public:
B() : A(0,0)
{
}
};
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.
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 przypadku B() : 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