С++: Инициализация наследуемого поля
У меня вопрос об инициализации наследуемых членов в конструкторе производного класса. Пример кода:
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
in B
(поскольку родительские конструкторы выполняются до инициализации элемента унаследованного класса). Где ошибка в моих рассуждениях? Что действительно происходит в этом коде?
EDIT
: Я знаю о других возможностях инициализации этого члена (базовый конструктор или назначение в производном конструкторе), но я хочу понять, почему это незаконно в том, как я это пробовал? Некоторые особенности языка С++ или такие? Пожалуйста, укажите, пожалуйста, параграф в стандарте С++.
Ответы
Ответ 1
Вам нужно создать конструктор для A (он может быть защищен, поэтому только B может его вызывать), который инициализирует m_int так же, как и у вас, затем вы вызываете :A(0)
, где у вас :m_int(0)
Вы также можете просто установить m_int = 0
в тело конструктора B. Он доступен (как вы описали), он просто недоступен в синтаксисе специального конструктора.
Ответ 2
Что вы хотите, так это:
class A{
public:
A() : m_int(0);
int m_int;
};
так что m_int
инициализируется в правильном месте.
Edit:
Из комментария выше, причина, по которой компилятор жалуется, когда вы пытаетесь инициализировать переменную m_int
в B
, состоит в том, что она уже была инициализирована конструктором A
. То есть вы не можете повторно инициализировать что-то, только переназначить. Итак, вы можете переназначить, как сказал Бен Джексон выше, или вы можете инициализировать в нужном месте.
Ответ 3
Чтобы создать экземпляр класса B
, вы сначала создаете экземпляр класса A
. Во время создания экземпляра m_int
инициализируется. После этой инициализации вызывается конструктор B
, поэтому вы не можете повторно инициализировать m_int
. Если это ваша цель, вы можете реализовать конструктор для A
, который принимает int, а затем вызывает это в B
списке инициализации:
class A
{
public:
A(int x): m_int(x) {}
int m_int;
};
class B: public A
{
public:
B(): A(2) {}
};
Ответ 4
сделать конструктор в A
и использовать B(): A (2) {}
insteed of B(): m_int (0) {}
его работа.