В Effective С++ (3-е изд.), пункт 2 (Предпочитают const
, enum
и inline
- #define
), сегмент кода для констант, специфичных для класса, читает:
class GamePlayer {
private:
static const int NumTurns = 5; // constant declaration
int scores[NumTurns]; // use of constant
...
};
В книге затем (по моим собственным словам) говорится, что static const int NumTurns = 5;
не является определением, которое обычно требуется для С++ для членов класса, если оно не является статической интегральной константой, адрес которой никогда не используется. Если приведенное выше значение неверно для константы или если компилятор настаивает на определении по какой-либо причине, определение должно быть представлено в файле реализации следующим образом:
const int GamePlayer::NumTurns; // definition of NumTurns; see
// below for why no value is given
Согласно книге (также по моим собственным словам), в определении не указано значение, поскольку оно уже указано в объявлении.
Это запутывает то, что, как я думал, я уже знаю об определениях декларации и определения (и я дважды проверял на Google, прежде чем задавать этот вопрос):
- Почему
static const int NumTurns = 5
не определение? Является лиNumTurns
не инициализировано значением5
здесь, и не так ли, когда декларация и определение происходят вместе, она называется инициализацией? - Почему интегральные константы
static
не требуют определения? - Почему второй фрагмент кода считается определением, когда значение не определено, но декларация внутри класса, которая содержит значение, по-прежнему не является одной (в основном, для моего первого вопроса)?
- Не инициализирует ли определение? Почему здесь не нарушено правило "только одного определения"?
Возможно, я просто запутываю себя здесь в этот момент, поэтому кто-то любезно перевоспитает меня с нуля: почему эти две строки объявлений и определений кода, а не другие, и есть ли там какие-либо примеры инициализации? Инициализация также является определением?
Кредит: фрагменты кода напрямую цитируются в книге.
Изменить: с дополнительной ссылкой на В чем разница между определением и объявлением?
- В объявлении вводится идентификатор и тип
- Определение создает и реализует
Итак, да... это не похоже на то, что происходит здесь.
Изменить 2. Я считаю, что компиляторы могут оптимизировать статическую интегральную константу, не сохраняя ее в памяти и просто заменяя ее встроенной в код. Но если используется адрес NumTurns
, почему декларация не меняется в объявление + автоматически, так как экземпляр уже существует?
Изменить 3: (Это редактирование имеет меньше общего с исходным вопросом, но по-прежнему остается выдающимся от него. Я размещаю его здесь, так что мне не нужно копировать-вставлять комментарии в каждый ответ ниже. Пожалуйста, ответьте мне для этого в комментариях Спасибо!)
Спасибо за ответы. Теперь моя голова намного яснее, но последний вопрос из Edit 2 все еще остается: если компилятор обнаруживает условия в программе, где требуется определение (например, &NumTurns
), почему это не просто автоматически reinterpret static const int NumTurns = 5;
как объявление и определение вместо объявления только? У этого синтаксиса есть определение где-нибудь еще в программе.
Я исхожу из фона Java в школе и не нуждаюсь в том, чтобы сделать отдельные определения, подобные этим для статических членов, описанным выше. Я знаю, что С++ отличается, но я хочу знать, почему это так. Статический интегральный член, заменяемый inline, если адрес никогда не используется, скорее похож на оптимизацию на меня, чем на фундаментальную функцию, поэтому почему мне нужно ее обойти (предоставление отдельного утверждения в качестве определения, когда условия не являются встречается, хотя исходный синтаксис оператора достаточен), а не наоборот (компилятор, рассматривающий исходный оператор как определение, когда необходимо иметь его с синтаксисом)?