Инициализация статического члена данных

Почему не происходит инициализация статического члена данных по умолчанию? В следующем примере

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

0

Решение

Статический член должен быть определен вне определения класса. Он будет инициализирован (может быть также инициализирован по умолчанию) в это время.

Следующее описание из проекта стандарта о static Переменные-члены должны объяснить, почему они не инициализируются по умолчанию в объявлении класса.

9.4.2 Статические данные членов

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

3

Другие решения

struct Y
{
static data_member m;
Y(){ cout << "Y\n"; }
~Y(){ cout << "~Y\n"; }
};

Только это объявляет m, Поскольку все, что знает компилятор, Y::m определяется в другой единице перевода. Так как члены статических данных являются индивидуальными для каждого класса, вы должны иметь возможность объявлять их, не определяя их, или вы не сможете поместить определение класса в файл заголовка, не нарушив Правило единого определения при включении заголовка в разные переводческие единицы.

data_member Y::m;

Это определяет м и вызовет вызов конструктора.

2

static члены данных объявленный в class определение. Они должны быть определенный (один раз) вне этого, обычно в соответствующем cpp файл:

data_member Y::m;

здесь вы увидите, что по умолчанию вызывается ctor.

2

Основной ответ:
С учениками это как с функциями.
У нас есть декларации и определения.
Вы «объявляете» их уровень существования @class, и «определение» производится конструктором.
Со статическим членом его сложнее. Они не «связаны с экземпляром», и конструктор не будет «определять» их. Вы должны сделать это самостоятельно вне класса:

Type CLASS::member;

Кстати, это довольно плохая практика использовать статические элементы.

Вместо этого используйте статическую функцию:

class Foo{
public:
Type &getMember(){
static Type member;
return member;
}
};
0
По вопросам рекламы [email protected]