2010-10-21 4 views
18

У меня вопрос об инициализации наследуемых членов в конструкторе производного класса. Пример кода:C++: Инициализация унаследованного поля

class A 
    { 
public: 
    int m_int; 
    }; 

class B: public A 
    { 
public: 
    B():m_int(0){} 
    }; 

Этот код дает мне следующий вывод:

In constructor 'B::B()': Line 10: error: class 'B' does not have any field named 'm_int'

(см http://codepad.org/tn1weFFP)

Я предполагаю, почему это происходит? m_int должен быть членом B, а родительский класс A должен быть инициализирован, когда инициализация m_int в B происходит (поскольку родительские конструкторы выполняются до инициализации члена наследуемого класса). Где ошибка в моих рассуждениях? Что на самом деле происходит в этом коде?

EDIT: Я знаю о других возможностях инициализации этого элемента (базовый конструктор или назначение в производном конструкторе), но я хочу понять, почему это незаконно в том, как я это пробовал? Некоторые особенности языка C++ или такие? Пожалуйста, укажите, пожалуйста, параграф в стандарте C++.

ответ

18

Вам нужно сделать конструктор для A (она может быть защищена, так только B можно назвать), который инициализирует m_int так же, как у вас есть, то вы вызовете :A(0), где у вас есть :m_int(0)

Вы также можете просто установить m_int = 0 в теле конструктора B. Он доступен (как описано), он просто недоступен в синтаксисе специального конструктора.

+5

Это хороший ответ, но я просто хотел бы добавить некоторое объяснение. Когда вы используете оператор:, вы сообщаете компилятору, что перед тем, как он сделает что-нибудь еще, он должен запустить эти инструкции. В основном вы устанавливаете переменную перед тем, как запускается родительский конструктор (или что-то еще). Поэтому переменная не существует. : A(), m_int (0) также должны работать.По умолчанию, если вы не используете:, компилятор будет запускать конструктор базовых классов. Другими словами, если вы ничего не сделаете, C++ будет делать вещи по умолчанию для вас, если вы начнете задавать вещи, предполагается, что вы знаете, что делаете. –

+0

Хммм ... Насколько я знаю, конструктор родительского класса всегда запускается перед любыми другими инициализациями, поэтому переменная 'm_int' уже существует, когда я пытаюсь ее инициализировать. Так что это не должно быть проблемой ... – Haspemulator

+0

@Haspemulator Да, он уже существует, но именно поэтому вы получаете ошибку. Он уже инициализируется по умолчанию конструктором A. Вы не можете повторно инициализировать переменную в конструкторе B. Вы можете переназначить, как заявляет Бен Джексон выше ('m_int = 0'), и об этом в этот момент. – wheaties

4

Что вы хотите, это:

class A{ 
public: 
    A() : m_int(0); 
    int m_int; 
}; 

так что m_int инициализируется в правильном месте.

Edit:

Из указанного выше комментария, причина компилятор жалуется, когда вы пытаетесь инициализировать переменную m_int в B является то, что он уже был инициализирован конструктором A. То есть вы не можете повторно инициализировать что-то, только переназначить. Таким образом, вы можете переназначить, как сказал Бен Джексон выше, или вы можете инициализировать в нужном месте.

4

Чтобы создать экземпляр класса B, вы сначала создаете экземпляр класса A. Во время этого экземпляра инициализируется m_int. После этой инициализации вызывается конструктор b, поэтому вы не можете повторно инициализировать m_int. Если это ваша цель, то вы можете реализовать конструктор для A, который принимает Int и затем вызвать, что в списке инициализации B «s:

class A 
{ 
public: 
    A(int x): m_int(x) {} 
    int m_int; 
}; 

class B: public A 
{ 
public: 
    B(): A(2) {} 
}; 
+0

Есть ли причина, по которой он недоступен в списке инициализации? Я знаю о других возможностях инициализации этого члена (базовый конструктор или назначение в производном конструкторе), но я хочу понять, почему это незаконно в том, как я пытаюсь? Некоторые особенности языка C++ или такие? Пожалуйста, укажите, пожалуйста, параграф в стандарте C++. – Haspemulator

+0

Это две вещи: производные классы сначала создают базовые классы, а члены инициализируются в том порядке, в котором они объявлены, а не в порядке их появления в списке инициализации. Поэтому элементы базы сначала инициализируются, и вы не можете их повторно инициализировать. –

0

сделать конструктор в A и использование B(): A (2) {} insteed of B(): m_int (0) {} его работа.

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