Почему мы должны определить постоянный статический член, который инициализируется в классе - PullRequest
2 голосов
/ 20 марта 2012

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

enter image description here

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

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

Ответы [ 2 ]

5 голосов
/ 20 марта 2012

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

4 голосов
/ 20 марта 2012

Вам необходимо определить статическую константу num вне класса в файле cpp, только если ваш код принимает его адрес. Это называется Определение вне класса .
Если ваш код не принимает адрес num, то In-class Initialization будет работать нормально.

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

Бьярне Состояния :

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...