Почему я не могу этого сделать?
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
Почему я не могу этого сделать?
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
Ответы:
Вы не можете инициализировать a
и b
in, B
потому что они не являются членами B
. Они являются членами A
, поэтому только A
могут их инициализировать. Вы можете сделать их общедоступными, а затем выполнить присваивание B
, но это не рекомендуется, поскольку это разрушит инкапсуляцию. Вместо этого создайте конструктор, A
позволяющий B
(или любому подклассу A
) инициализировать их:
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
и b
в B::B()
потому , что они являются частными. Вы не можете инициализировать их, потому что они не являются членами class B
. Если вы сделали их общедоступными или защищенными, вы можете назначить их в теле B::B()
.
a
и b
...» и изменил его на «Вы не можете инициализировать ...», не убедившись, что остальная часть предложения имеет смысл. Сообщение отредактировано.
Оставляя в стороне тот факт, что они есть private
, поскольку a
и b
являются членами A
, они предназначены для инициализации A
конструкторами, а не конструкторами какого-либо другого класса (производными или нет).
Пытаться:
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) {}
};
Почему-то никто не перечислил самый простой способ:
class A
{
public:
int a, b;
};
class B : public A
{
B()
{
a = 0;
b = 0;
}
};
Вы не можете получить доступ к базовым членам в списке инициализаторов, но сам конструктор, как и любой другой метод-член, может обращаться public
и к protected
членам базового класса.
B
выделении экземпляра , затем он будет назначен внутри B
конструктора. Но я также думаю, что компилятор все еще может это оптимизировать.
class A
мы не можем полагаться a
и b
на инициализацию. class C : public A
Например, любая реализация может забыть позвонить a=0;
и оставить a
неинициализированным.
class A { int a = 0;};
), либо в конструкторе базового класса. Подклассы по-прежнему могут повторно инициализировать их в своем конструкторе по мере необходимости.
# 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;
}
Это рабочий пример на случай, если вы хотите инициализировать члены данных базового класса, присутствующие в объекте производного класса, в то время как вы хотите передать эти значения, взаимодействуя через вызов конструктора производного класса.
Хотя это полезно в редких случаях (если бы это было не так, язык позволил бы это напрямую), взгляните на идиому Base from Member . Это не решение без кода, вам придется добавить дополнительный уровень наследования, но оно выполняет свою работу. Чтобы избежать шаблонного кода, вы можете использовать реализацию boost
Почему ты не можешь этого сделать? Потому что язык не позволяет вам инициализировать члены базового класса в списке инициализаторов производного класса.
Как это сделать? Как это:
class A
{
public:
A(int a, int b) : a_(a), b_(b) {};
int a_, b_;
};
class B : public A
{
public:
B() : A(0,0)
{
}
};
Если вы не укажете видимость для члена класса, по умолчанию она будет закрытой. Вы должны сделать своих участников закрытыми или защищенными, если хотите получить к ним доступ в подклассе.
Совокупные классы, такие как A в вашем примере (*), должны иметь свои члены общедоступные и не иметь определяемых пользователем конструкторов. Они инициализируются списком инициализаторов, например, A a {0,0};
или в вашем случае B() : A({0,0}){}
. Члены базового агрегатного класса не могут быть индивидуально инициализированы в конструкторе производного класса.
(*) Если быть точным, как было правильно сказано, оригинал class A
не является агрегатом из-за частных нестатических членов