2012-08-07 3 views
2

такой код, и с ошибкой: «незаконная инициализация члена:« 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 

} 
+0

возможный дубликат [Инициализировать защищенные члены родителя с списком инициализации (C++)] (http://stackoverflow.com/questions/2290733/initialize-parents-protected-members-with-initialization-list-c) – iammilind

+0

перед тем, как задать этот вопрос, Я искал, но не нашел никого! –

ответ

8

К тому времени, когда вызывается конструктор производного класса, базовый класс уже должен быть сконструирован. Так что уже слишком поздно. Чтобы понять, почему так должно быть, рассмотрите:

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 перестроить его с другим значением?

+0

отличное объяснение! –

0

Потому что базовый класс может захотеть инициализировать вещи своим путем. Правильный метод состоит в том, чтобы вызвать базовые конструкторы в списке инициализаторов и позволить базовому ctor инициализировать себя.

2

См. this answer для более полного объяснения того, что здесь происходит. В принципе, вы не можете инициализировать A::a в инициализаторе B, поскольку он плохо сформирован в соответствии со стандартом.

0

Еще одна важная часть информации - помните, что если класс не инициализирует объект-член через список инициализации конструктора, тогда конструктор по умолчанию для этого элемента будет вызываться до того, как будет выполнен первый оператор в конструкторе базового класса. Когда вы используете инициализатор, то, что вы на самом деле делаете, это указание конструктора, который будет использоваться INSTEAD конструктора по умолчанию.

Очевидно, что когда вы строите производный класс, родительский член класса уже сконструирован, поэтому вы не можете снова восстановить базовый элемент, что вы пытаетесь сделать в этом примере, включив его в производный класс список инициализации.

Как и в сторону, если вы все вы хотите иметь производный класс быть в состоянии установить значение A :: к определенному значению, то используйте следующий код вместо:

B::B() 
{ 
    a = 10; 
} 
Смежные вопросы

 Смежные вопросы