Определение статических элементов в С++

Я пытаюсь определить общедоступную статическую переменную следующим образом:

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

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

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

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

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

Спасибо!

Ответ 1

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

От Бьярне Страуструпа C++ FAQ по стилю и технике:

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

(2.) Почему члены const могут быть инициализированы?

[ Диргентки сказал, что лучше ]

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

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

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

Ответ 2

Вам нужно будет инициализировать статическую переменную в файле .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
}

Ответ 3

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

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

Почему разрешено инициализировать константные члены?

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

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

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

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

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

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

Нет, они:

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

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

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

Ответ 4

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

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

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

Ответ 5

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 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();      
}