Список инициализации члена C++
Пожалуйста, объясните, как использовать списки инициализации членов. У меня есть класс, объявленный в .h
файл и .cpp
файл как это:
class Example
{
private:
int m_top;
const int m_size;
...
public:
Example ( int size, int grow_by = 1 ) : m_size(5), m_top(-1);
...
~Example();
};
Я инициализирую m_size
на создание объекта из-за const
, Как мне написать конструктор? Должен ли я повторить : m_size(5), m_top(-1)
или я могу пропустить этот шаг?
Example::Example( int size, int grow_by)
{
... some code here
}
или же
Example::Example( int size, int grow_by) : m_size(5), m_top(-1)
{
... some code here
}
6 ответов
Это список инициализации:
Example::Example( int size, int grow_by) : m_size(5), m_top(-1)
{
... some code here
}
и это должно быть сделано только в файле cpp.
Разве вы не получаете ошибку, когда вы делаете это, как вы сделали в заголовке в вашем примере?
Просто чтобы уточнить кое-что, что появилось в некоторых других ответах...
Не требуется, чтобы список инициализации был либо в исходном (.cpp), либо в заголовочном (.h) файле. Фактически, компилятор не различает два типа файлов. Важное различие между декларацией разработчика и его определением. Список инициализации идет с определением, а не с объявлением.
Обычно объявление находится в заголовочном файле, а определение - в исходном файле, однако это не является обязательным требованием языка (т.е. оно будет компилироваться). Нет ничего необычного в том, чтобы предоставлять определения конструктора, встроенные в объявление класса, когда конструктор пустой или короткий. В этом случае список инициализации будет находиться внутри объявления класса, которое, вероятно, будет находиться в заголовочном файле.
MyClass.h
class MyClass
{
public:
MyClass(int value) : m_value(value)
{}
private:
int m_value;
};
Список инициализаторов элементов является частью определения в исходном файле.
Запишите это в файл cpp:
Example ( int size, int grow_by) : m_size(5), m_top(-1)
{
}
Заголовочный файл должен иметь только:
Example ( int size, int grow_by = 1 );
Заголовочный файл объявляет только конструктор, список Member Initializer не является частью объявления.
Добавляя к другим ответам, самое важное, что следует помнить о списке инициализации, это то, что the order of initialization is decided in the order in which the data members are declared, not the the order in which you have initialized the data members using initialization list
Рассмотрим пример (Ваш):
class Example
{
private:
int m_top;
const int m_size;
...
public:
Example ( int size, int grow_by = 1 ) : m_size(5), m_top(-1){}
/* Though size is initialized with a value first
But it is m_top variable that is assigned value -1
before m_size is assigned value 5 */
...
~Example(){}
};
Если кто-то не знает о вышеизложенном, это может привести к очень серьезным последствиям.
В C++11 вы можете использовать нестатическую инициализацию членов данных. Это особенно полезно, если у вас есть несколько конструкторов, которым нужно общее значение для переменной-члена.
class Example
{
private:
int m_top = -1;
const int m_size = 5;
...
public:
Example ( int size, int grow_by = 1 );
...
~Example();
};
...
Example::Example( int size, int grow_by )
{
... some code here
}
Вы можете переопределить значение в конструкторе, если вам нужно.
Вы не можете иметь инициализирующий список как в заголовке, так и в cpp. Список должен быть в котором файл определяет ваш конструктор. Также вы должны включить тело для конструктора, даже если оно пустое.
С другой стороны, вы должны указывать только аргументы по умолчанию в прототипе функции, а не в определении.