2010-08-21 4 views
22

Я пытаюсь определить общественную статическую переменную как это:Определение статических членов в C++

public : 
     static int j=0;  //or any other value too 

Я получаю ошибку компиляции на этой самой линии: ISO C++ запрещает в классе инициализации неконстантного статики член `j '.

  1. Почему это запрещено в C++?

  2. Почему разрешено инициализировать элементы-члены const?

  3. Означает ли это, что статические переменные в C++ не инициализируются 0, как в C?

Спасибо!

ответ

14

(1.) Почему это запрещено в C++?

От Bjarne Stroustrup's C++ Style and Technique FAQ: A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects.

(2.) Почему константные члены позволили инициализировать?

[dirkgently said it better]

(3) Означает ли это, что статические переменные в C++ не инициализируются с 0, как в C?

Насколько я знаю, до тех пор, как вы объявляете статический вар член в .cpp будет нулевой инициализируется, если не указано иное:

// in some .cpp 
int Test::j; // j = int(); 
+0

Спасибо за отличный ответ, вы мешали мне вытащить мой звук из головы! У меня есть один вопрос, есть ли какой-либо возможный способ указать нулевой указатель при определении ссылочных элементов? –

+1

@TimVisee Не уверен, что это возможно - по крайней мере, в переносном режиме, но не в UB, но вы получите недопустимую ссылку. Если вам нужна семантика NULL, просто используйте указатель или, возможно, используйте что-то вроде Boost Optional. –

16

Вам придется инициализировать статическую переменную в файле .cpp, а не в объявлении класса.

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

//Header file 
class Test 
{ 
    public: 
    static int j; 
}; 

//In cpp file 

//Initialize static variables here. 
int Test::j = 0; 

//Constructor 
Test::Test(void) 
{ 
    //Class initialize code 
} 
17

Почему это не разрешено в C++?

До тех пор, пока вы не определите его, переменная не станет l-значением.

Почему разрешено инициализировать элементы-члены const?

Даже в этом случае требуется определение, если вы собираетесь принять адрес переменной.

9.4.2 Статические элементы данных

объявления статических данных состоит в определении класса не определения и может быть из неполного типа, кроме сорта -qualified void. Определение для статического элемента данных должно появляться в области пространства имен , охватывающей определение класса элемента . В определении в области пространства имен имя статического элемента данных должно быть присвоено по его названию, используя оператор :: . Выражение инициализатора в определении статических данных элемента находится в рамках своего класса

Кроме того, это прежде всего использование артефакта, так что вы можете написать:

class S { 
     static const int size = 42; 
     float array[ size ]; 
}; 

ли эти средние статические переменные в C++ не инициализируются с 0 как в C?

Нет они:

3.6.2 Инициализация нелокальных переменных

Переменные со статической продолжительностью хранения (3.7.1) или продолжительности хранения нити (3.7. 2) должно быть нулинициализировано (8.5) перед началом любой другой инициализации место.

Хотя в C++ 0x ситуация становится немного более сложной. Теперь все литеральные типы могут быть инициализированы (в отличие от только интегральных типов в текущем стандарте), что означало бы, что все типы скаляров (включенные с плавающей точкой) и некоторые типы классов теперь могут быть инициализированы с использованием инициализатора в объявлении.

+0

Почему определение статического целочисленного значения const не требуется, если адрес не занят? Он (static-const-int, определенный в .h) компилируется, успешно связывается без определения. Если это так, поскольку, когда C++ разрешает этот тип объявления без определения, так как C++ 98? с C++ 03? Аутентичные источники, пожалуйста. Стандарт C++ (9.4.2) не синхронизируется с компиляторами. В нем упоминается, что член должен быть определен, если он используется в программе. Итак, я скажу вам, я не ищу цитаты из C++ Standard. Что будет хорошо, замечания комитета по изменениям в системе GCC/C++. – smRaj

8

Короткий ответ:

Это эквивалентно заявлению extern int Test_j = 0;.

Если это скомпилировано, что произойдет? Каждый исходный файл, включающий заголовочный файл вашего класса, будет определять символ Test :: j, инициализированный равным 0. Компонент имеет тенденцию не любить это.

+4

+1.«extern» проливает свет на характер проблемы здесь. – Cheezmeister

2
class GetData   
{  
private:  
static int integer; //Static variable must be defined with the extension of keyword static;  
public:  
static void enter(int x)  
{  
integer = x; //static variable passed through the static function  
} 
static int show() //declared and defined 
{ 
    return integer; //will return the integer's value 
}   
};   
int GetData::integer = 0; //Definition of the static variable  
int main()  
{  
    GetData::enter(234); //value has been passed through the static function enter. Note that class containing static variables may not have the object in main. They can be called by scope resolution operator in main. 
    cout<<GetData::show();  
}  
Смежные вопросы