Почему нельзя инициализировать член данных базового класса в списке инициализатора конструктора производного класса?
Таков код с ошибкой:"недопустимая инициализация члена:" a "не является базой или членом", что означает информация об ошибке и почему??
class A{
public:
int a;
};
class B:public A{
public:
B();
};
B::B():a(10){ // put "a(10)" into the constructor body is right
}
4 ответа
К тому времени, когда вызывается конструктор производного класса, базовый класс уже должен быть создан. Так что уже слишком поздно. Чтобы понять, почему так должно быть, подумайте:
class Base
{
public:
int i;
Base(int q) : i(q) { ; }
};
class Middle : public Base
{
public:
Middle() : Base(2) { printf("i=%d\n", i); }
};
class Derived : public Middle
{
public:
Derived() : i(3) { ; }
}
Теперь подумай об этом. Middle
Конструктор должен работать до Derived
конструктор. И Middle
конструктор гарантирует, что i
2. Так как же Derived
конструктор позже восстановить его с другим значением?
Смотрите этот ответ для более полного объяснения того, что происходит здесь. По сути, вы не можете инициализировать A::a
в инициализаторе B
потому что он плохо сформирован в соответствии со стандартом.
Еще одна важная часть информации - помните, что если класс не инициализирует объект-член через список инициализации конструктора, конструктор по умолчанию для этого члена будет вызван до того, как будет выполнен первый оператор в конструкторе базового класса. Когда вы используете инициализатор, вы фактически указываете конструктор, который будет использоваться INSTEAD конструктора по умолчанию.
Очевидно, что когда вы создаете производный класс, родительский элемент класса, таким образом, уже создан, поэтому вы не можете восстановить базовый элемент снова, что вы и пытаетесь сделать в этом примере, включив его в список инициализации производного класса.
Кроме того, если вы хотите, чтобы производный класс мог установить значение A::a для определенного значения, тогда используйте вместо этого следующий код:
B::B()
{
a = 10;
}
Потому что базовый класс может захотеть инициализировать вещи по-своему. Надлежащий метод заключается в вызове базовых конструкторов в списке инициализатора и позволяет базовому ctor инициализировать себя.