Почему переменная const, объявленная как член класса, все еще может быть изменена?
Если переменная const, которая была назначена, все еще может быть переназначена, то это не const? Взять, к примеру:
struct ss
{
const int m = 1024;
ss()
{
}
ss(int m) : m(m)
{
}
};
ss sa;
ss sb(-1);
cout << sa.m << endl;
cout << sb.m << endl;
Ничего себе, м не является постоянным в конце концов!
> /* Ouput: > > 1024 > -1 > > */
2 ответа
ss(int m) : m(m)
{
}
Это говорит о том, что когда класс ss
инициализирован, его член m
инициализируется с помощью параметра m
, Член m
на самом деле не может быть изменено, но оно может быть инициализировано, как и любой другой const
объект. Обратите внимание, что если бы мы сделали вместо
ss(int m)
{
this->m = m;
}
тогда у нас будет проблема, так как ss::m
должен быть инициализирован. И если ss::m
был класс с конструктором по умолчанию, то в
ss(FooClass m)
{
this->m = m;
}
нормально не инициализировать ss::m
явно (так как это будет просто построено по умолчанию), но строка в теле конструктора будет отклонена, так как это изменит ss::m
после того, как он уже был инициализирован.
Изменить: Ой, я не понял ваш первоначальный вопрос.
Инициализатор фигурной или равной скобки, такой как
const int m = 1024;
используется только если член не указан в инициализаторе ctor. Другими словами, поскольку конструктор по умолчанию явно не инициализируется m
используется значение 1024. Но ss::ss(int)
действительно инициализирует m
, так что инициализатор скобки или равный игнорируется.
Ваш пример имеет дело только с различными режимами инициализации, переназначение здесь не происходит. То, что вы видите, это эффект того, что список инициализаторов конструкторов предпочтительнее, чем инициализатор членов класса in, это видно из черновика стандартного раздела C++. 12.6.2
Инициализация баз и членов параграфа 9, в котором говорится:
Если данный элемент нестатических данных имеет инициализатор скобок или равных и инициализатор mem, выполняется инициализация, заданная инициализатором mem, и инициализатор скобок или равных равен: игнорируются. [Пример: дано
struct A { int i = / some integer expression with side effects / ; A(int arg) : i(arg) { } // ... };
конструктор A(int) просто инициализирует i значением arg, и побочные эффекты в инициализаторе i brace-orequal не будут иметь места. - конец примера]
Как уже обсуждалось в статье: Является ли новая функция инициализации члена C++11 при объявлении устаревшими списками инициализации? Это полезная функция, поскольку она позволяет вам задавать переменные-члены по умолчанию, а затем переопределять эти значения по умолчанию на основе вызываемого конструктора.