Почему мы должны определить постоянный статический член, который инициализируется в классе
Как мы знаем, можно инициализировать интегральные константные статические члены внутри структуры класса. Это полезно, когда константа используется в структуре класса после инициализации. Например, она может использоваться как размер массива 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
целочисленные значения могут иметь Инициализацию в классе, взятие адреса таких переменных не допускается. Можно взять адрес статического члена, если (и только если) у него есть определение вне класса, потому что тогда компилятор должен поместить их в память.