2013-08-28 1 views
21

Мне сложно найти хиты в Google для этого.Member initializer не называет нестатического элемента данных или базового класса

struct a { 
    float m_x; 
    float m_z; 
public: 
    a(float x): m_x(x) {} 
}; 

class b : public a { 
    b(float z): m_z(z) {} 
}; 

На лязгом 3.2:

error: member initializer 'm_z' does not name a non-static data member or base class 
    b(float z): m_z(z) {} 
+0

Почему? Я еще не сделал «злого наследственного алмаза». @AndreyT принятый ответ в этом вопросе говорит, чтобы сделать базовый счет. У меня есть ... о. Думаю, мне нужно называть базовый класс ctor, а не член ctor. ОК. –

+0

@WhozCraig: даже если это виртуальная база, она все равно не позволит вам инициализировать * косвенные * члены. Виртуальное наследование может потребовать инициализации косвенных * базис *, но не членов. – AnT

+1

@Steven Lu: В принятом ответе говорится, что 'a :: m_z' может быть инициализирован только из списка инициализаторов конструктора' a'. Он не может быть указан в списке инициализаторов конструктора 'b' (как в вашем коде).Язык этого не позволяет. В этом-то и дело. То есть вам нужно добавить другой параметр в конструктор 'a' специально для' m_z' (как и для 'm_x') и передать начальное значение из' b' через этот конструктор. BTW, в вашем коде выше вы должны обратиться к конструктору 'a' из конструктора' b'. В противном случае он не будет компилироваться, поскольку у вас нет конструктора по умолчанию в 'a'. – AnT

ответ

26

Нет, вы не можете инициализировать члены базового класса из списка инициализаторов непосредственно. Это происходит потому, что порядок инициализации протекает таким образом,

С ++ Стандартный n3337 § 12.6.2/10

В не делегировании конструктор, инициализации переходит в следующем порядке:

- Во-первых, и только для конструктора из самого производного класса (1.8) виртуальные базовые классы инициализируются в порядке , они появляются на первом пересечении слева направо влево-вправо направленного ациклического графа базы c lasses, где «left-right-right» - это порядок внешний вид базовых классов в производном классе base-specifier-list.

- Тогда прямые базовые классы инициализируются в порядке декларации, как они появляются в базовом спецификаторе-листе (независимо от порядка MEM-инициализаторы).

- Затем нестатические элементы данных инициализируются в порядке, они были объявлены в определении класса (опять же, независимо от порядка MEM-инициализаторах).

- И наконец, составная инструкция корпуса конструктора выполнена.

[Примечание: заказ декларации уполномочен гарантировать, что субобъекты базы и уничтожены в порядке, обратном порядку . - конец примечание]

Таким образом, вы можете указать конструктор в базовом классе (она может быть защищена) и использовать этот один в списке инициализации производного класса (should be preferred), или вы можете назначить к члену базового класса в производном классе ctor body (другое поведение, другой эффект, а также менее эффективный - вы назначаете элемент инициализированного по умолчанию (уже имеет значение)).

В первом случае вы можете написать так:

struct A { 
    float m_x; 
    float m_z; 
    A(){} 
protected: 
    A(float x): m_x(x) {} 
}; 

class B : public A { 
public: 
    B(float z) : A(z) {} 
    // alternatively 
    // B(float z) { 
    //  m_x = z; 
    // } 
}; 

int main(){ 
    B b(1); 
    return 0; 
} 
Смежные вопросы