Почему мы должны определить постоянный статический член, который инициализируется в классе

Как мы знаем, можно инициализировать интегральные константные статические члены внутри структуры класса. Это полезно, когда константа используется в структуре класса после инициализации. Например, она может использоваться как размер массива int. Смотри код следующий:

class MyClass{
static const int num = 100;
int elems[num];
...
};

Но мы все еще должны определить член num вне определения класса:

const int MyClass::num;

Я не знаю, почему мы должны так поступать. Может кто-нибудь сказать мне, почему? Большое спасибо.

Кроме того, я пишу следующий код:

#include <iostream>
using namespace std;

class MyClass{
public:
MyClass()
{
    cout << "instruct class MyClass!" << endl;
}
static const int num = 100;
int elems[num];
};

//const int MyClass::num;

int main()
{
MyClass a;
const int *b = &(a.num);
cout << "&(a.num): " << &(a.num) << endl;
cout << "a.num: " << a.num << endl;
cout << "*b: " << *b << endl;
}

Хорошо работает на Visual Studio 2008:

Но я удалил код, который определяет член num вне класса.

Я очень смущен. Может ли кто-нибудь истолковать это для меня?

2 ответа

Решение

Инициализация в классе в основном используется для получения константного выражения. Для этого важна только ценность. Как только вы берете адрес объекта или привязываете его к ссылке, компилятору также требуется место для объекта. Это фактически то, что дает определение.

Вам нужно будет определить статическую константу num вне класса в файле cpp, только если ваш код берет его адрес. Это называется определением " вне класса".
Если ваш код не принимает адрес numТогда инициализация в классе будет работать нормально.

Обоснование:

Бьярне заявляет:

"C++ требует, чтобы у каждого объекта было уникальное определение. Это правило было бы нарушено, если бы C++ допускал определение сущностей в классе, которые должны были храниться в памяти как объекты".

Обратите внимание, что только static const целые числа могут рассматриваться как константы времени компиляции. Компилятор знает, что целочисленное значение не изменится в любое время и, следовательно, он может применить свою собственную магию и применить оптимизации, компилятор просто вставляет такие члены класса, т. Е. Они больше не сохраняются в памяти, так как необходимость сохранения в памяти устраняется он дает таким переменным исключение из вышеупомянутого правила, упомянутого Бьярне.

Даже если static const целочисленные значения могут иметь Инициализацию в классе, взятие адреса таких переменных не допускается. Можно взять адрес статического члена, если (и только если) у него есть определение вне класса, потому что тогда компилятор должен поместить их в память.

Другие вопросы по тегам