Почему не происходит инициализация статического члена данных по умолчанию? В следующем примере
struct data_member
{
data_member(){ cout << "data_member\n"; }
~data_member(){ cout << "~data_member\n"; }
};
struct Y
{
static data_member m;
Y(){ cout << "Y\n"; }
~Y(){ cout << "~Y\n"; }
};
Y y; //call constructor of Y
но если мы удалим static
спецификатор от data_member m
он будет инициализирован по умолчанию.
struct data_member
{
data_member(){ cout << "data_member\n"; }
~data_member(){ cout << "~data_member\n"; }
};
struct Y
{
data_member m;
Y(){ cout << "Y\n"; }
~Y(){ cout << "~Y\n"; }
};
Y y; //call Y() and data_member()
Статический член должен быть определен вне определения класса. Он будет инициализирован (может быть также инициализирован по умолчанию) в это время.
Следующее описание из проекта стандарта о static
Переменные-члены должны объяснить, почему они не инициализируются по умолчанию в объявлении класса.
9.4.2 Статические данные членов
2 Объявление
static
член данных в своем определении класса не является определением и может иметь неполный тип, отличный от cv-qualifiedvoid
, Определение дляstatic
элемент данных должен появиться в области имен, включающей определение класса члена. В определении в области именного пространства имяstatic
член данных должен быть квалифицирован по имени класса с помощью оператора ::.
struct Y
{
static data_member m;
Y(){ cout << "Y\n"; }
~Y(){ cout << "~Y\n"; }
};
Только это объявляет m
, Поскольку все, что знает компилятор, Y::m
определяется в другой единице перевода. Так как члены статических данных являются индивидуальными для каждого класса, вы должны иметь возможность объявлять их, не определяя их, или вы не сможете поместить определение класса в файл заголовка, не нарушив Правило единого определения при включении заголовка в разные переводческие единицы.
data_member Y::m;
Это определяет м и вызовет вызов конструктора.
static
члены данных объявленный в class
определение. Они должны быть определенный (один раз) вне этого, обычно в соответствующем cpp
файл:
data_member Y::m;
здесь вы увидите, что по умолчанию вызывается ctor.
Основной ответ:
С учениками это как с функциями.
У нас есть декларации и определения.
Вы «объявляете» их уровень существования @class, и «определение» производится конструктором.
Со статическим членом его сложнее. Они не «связаны с экземпляром», и конструктор не будет «определять» их. Вы должны сделать это самостоятельно вне класса:
Type CLASS::member;
Кстати, это довольно плохая практика использовать статические элементы.
Вместо этого используйте статическую функцию:
class Foo{
public:
Type &getMember(){
static Type member;
return member;
}
};