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

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

Я очень запутался, может ли кто-нибудь мне это интерпретировать?


person XiaJun    schedule 20.03.2012    source источник


Ответы (2)


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

person Dietmar Kühl    schedule 20.03.2012
comment
Но компилятор может обрабатывать его так же, как он обрабатывает статические элементы шаблонов или встроенные функции, обе из которых имеют определения в нескольких файлах, но по-прежнему требуют одного адреса. - person James Kanze; 20.03.2012
comment
@JamesKanze: для статических членов шаблонов вам все еще нужно определение, которое на самом деле довольно раздражает, потому что неявные экземпляры для этого не работают. Думаю, его можно заставить вести себя как статические переменные во встроенных функциях. Насколько я понимаю, они работают, создавая функции со слабыми символами, которые отбрасываются во время компоновки. Однако язык в настоящее время требует определения, хотя компиляторы могут не настаивать на его наличии. - person Dietmar Kühl; 20.03.2012
comment
Я знаю. Я просто говорю, что технически не было бы проблемой не требовать определения, поскольку технология компилятора для поддержки, не требуя этого, необходима и в других контекстах. - person James Kanze; 20.03.2012

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

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

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

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

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

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

person Alok Save    schedule 20.03.2012
comment
Наконец я понял. Большое вам спасибо! Я очень признателен за ваш ответ! - person XiaJun; 21.03.2012