Это потому, что стандарт так говорит.
Обычно правило определения out-of-line применяется к static const
элементам:
Объявлениеэлемента данных static
в его определении класса является , а не определением.
Единственное исключение состоит в том, что, поскольку C ++ 11 целочисленные и enum static const
типы могут бытьинициализируется in-line.
См. [class.static.data] / 3 (выделено мной):
Если энергонезависимые const static
данныечлен имеет целочисленный или тип перечисления , его объявление в определении класса может указывать скобка-или-равный инициализатор , в котором каждый инициализатор-предложение , которое является выражением присваивания является константным выражением.
Как упомянул Бьярне :
Итакпочему существуют эти неудобные ограничения?Класс обычно объявляется в файле заголовка, а файл заголовка обычно включается во многие единицы перевода.Однако, чтобы избежать сложных правил компоновщика, C ++ требует, чтобы у каждого объекта было уникальное определение.Это правило было бы нарушено, если бы C ++ допускал в классе определение сущностей, которые должны были храниться в памяти как объекты.
Рациональным могло бы быть то, что целочисленные типы становятся константами времени компиляции, хотя я склоненне согласиться, потому что правило единого адреса в единицах компиляции все еще применяется, что означает, что компилятор должен по-прежнему испускать элементы static const
со слабой связью и заставить компоновщик сворачивать их, так же, как это происходит с множественно определенными шаблонами.В этот момент ограничение на целочисленные типы становится спорным, поскольку одно и то же сворачивание может быть применено к любому типу.Фактически, C ++ 17 «исправляет» это с помощью inline
членов:
class H {
private:
inline static const int i = 5;
inline static const float f = 1.0;
inline static const string s = "string";
};