Static const double не может иметь инициализатор в классе. почему это так?

Задача со следующим кодом - статический член типа "const double" не может иметь инициализатор в классе. Почему применимо только для 'const double'in следующего кода? Пожалуйста, помогите мне.

class sample{
   static const char mc = '?';
   static const double md = 2.2;
   static const bool mb = true;
};
const char sample::mc;
const double sample::md;
const bool sample::mb;
int main(){
}

Ответ 1

Логика, реализованная стандартом языка С++ 03, основана на следующем обосновании.

В С++ инициализатор является частью определения объекта. То, что вы пишете внутри класса для статических членов, на самом деле является только декларацией. Таким образом, формально говоря, указание инициализаторов для любых статических членов непосредственно внутри класса является "неправильным". Это противоречит общей концепции/определению понятия языка. Независимо от того, какие статические данные, объявленные внутри класса, должны быть определены позже. Это где у вас будет возможность указать инициализаторы.

Исключение из этого правила было сделано для статических целочисленных констант, так как такие константы в С++ могут формировать интегральные константные выражения (ICE). ICE играют важную роль в языке, и для того, чтобы они работали по назначению, значения интегральных констант должны быть видны во всех единицах перевода. Чтобы сделать значение некоторой постоянной видимой во всех единицах перевода, оно должно быть видимым в точке объявления. Для этого язык позволяет указать инициализатор непосредственно в классе.

Кроме того, на многих аппаратных платформах постоянные целочисленные операнды могут быть встроены непосредственно в машинные команды. Или константа может быть полностью устранена или заменена (например, умножение на 8 может быть реализовано как сдвиг на 3). Чтобы облегчить создание машинного кода со встроенными операндами и/или различными арифметическими оптимизациями, важно иметь значения интегральных констант во всех единицах трансляции.

Неинтегральные типы не имеют никаких функций, подобных ICE. Кроме того, аппаратные платформы обычно не позволяют встраивать нецелые операнды непосредственно в машинные команды. По этой причине вышеупомянутое "исключение из правил" не распространяется на нецелые типы. Он просто ничего не достигнет.

Ответ 2

Pre-С++ 11, только определение const интегральных типов может быть непосредственно инициализировано в определении класса. Это просто ограничение, налагаемое стандартом.

С С++ 11 это больше не применяется.

Ответ 3

С++ 03 не допускает инициализацию нестационарных неконстантных неинтегральных типов в классе. То есть С++ 03 допускает инициализацию в классе только статических константных интегральных типов, таких как static const int, static const long, static const char, static const wchar_t и т.д.

Но С++ 11 позволяет инициализировать неклассические неконстантные нецелые типы в классе:

class A
{
   const char x = '?';                   //C++11 only (non-static)
   static char y = '?';                  //C++11 only (non-const)
   static const char a = '?';            //C++03 and C++11
   char b = '?';                         //C++11 only (non-static and non-const)
   static const double c = 10.0;         //C++11 only (non-integral)
   std::string d = "hello";              //C++11 only (non-integral)
   static const std::string e = "world"; //C++11 only (non-integral)
};

Ответ 4

Компилятор предложил мне использовать constexpr вместо const:

static_consts.cpp:3:29: error: ‘constexpr’ needed for in-class initialization of static data member ‘const double sample::md’ of non-integral type [-fpermissive]
static_consts.cpp:7:22: error: ‘constexpr’ needed for in-class initialization of static data member ‘const double sample::md’ of non-integral type [-fpermissive]

Я только что принял предложение:

class sample{
   static const char mc = '?';
   static constexpr double md = 2.2;
   static const bool mb = true;
};
const char sample::mc;
const bool sample::mb;
int main(){
}

И теперь он просто компилируется (С++ 11).