Рассмотрим для примера такую задачу.
Имеется класс, для которого мы хотим иметь глобальный счетчик объектов этого класса. Простейшее решение очевидно:
struct T
{
static int count;
T() { count++; }
~T() { count--; }
}
int T::count = 0; // вот это (или аналогичный вариант со статической
// функцией-инициализатором) мне не нравится
но при этом мы должны "руками" установить начальное значение счетчика... что мне не нравится... ну и аналогичных ситуаций можно много придумать.
Вопрос: как можно организовать инициализацию статических членов класса, чтобы это не требовало явных действий человека, им пользующегося. Вот в Java вроде как можно при объявлении написать static int count = 0; и все ок...
Где-то читал, что все статические переменные и члены класса изначально инициализируются нулями. Эксперимент с доступными компиляторами это вроде подтверждает. Но, как я понимаю, это не оговорено стандартом и пользоваться этим нехорошо. Как быть?
Если нужна инициализация нулем, ничего, кроме определения int T::count, делать не нужно:
struct T {
static int count;
. . .
};
int T::count;
Стандарт гарантирует (3.6.2), что T::count, равно как и любой другой объект со static storage duration, в этом случае будет проинициализирован нулем.
<< J 1.0 alpha 4 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Если нужна инициализация нулем, ничего, кроме определения int T::count, делать не нужно:
ПК>ПК>struct T {
ПК> static int count;
ПК> . . .
ПК>};
ПК>int T::count;
ПК>Стандарт гарантирует (3.6.2), что T::count, равно как и любой другой объект со static storage duration, в этом случае будет проинициализирован нулем.
Спасибо... Буду внимательно изучать стандарт... А где его можно скачать (желательно на русском)?
Впрочем, все равно проблема остается — статический член нужно объявлять вне класса. Вообще непонятно, зачем так в языке сделано...
Здравствуйте Аноним, Вы писали:
А>Впрочем, все равно проблема остается — статический член нужно объявлять вне класса. Вообще непонятно, зачем так в языке сделано...
Тут уже много писалось что можно и внутри
struct FOO
{
static int& GetRefCount() {
static int refCount = 0;
return refCount;
}
FOO() {
GetRefCount()++;
}
~FOO() {
GetRefCount()--;
}
};
Здравствуйте Аноним, Вы писали:
А>Рассмотрим для примера такую задачу.
А>Имеется класс, для которого мы хотим иметь глобальный счетчик объектов этого класса. Простейшее решение очевидно:
А>А>struct T
А> {
А> static int count;
А> T() { count++; }
А> ~T() { count--; }
А> }
А>int T::count = 0; // вот это (или аналогичный вариант со статической
А> // функцией-инициализатором) мне не нравится
А>
А>но при этом мы должны "руками" установить начальное значение счетчика... что мне не нравится... ну и аналогичных ситуаций можно много придумать.
Если тебя не устраивает начальное значение 0, то устанваливать его тебе придется в любом случае "руками". Компилятор не телепат, он не может узнать, какое начальное значение тебе нужно.
А>Вопрос: как можно организовать инициализацию статических членов класса, чтобы это не требовало явных действий человека, им пользующегося.
Без явных действий человека все статические объекты инициализируются нулями.
А>Вот в Java вроде как можно при объявлении написать static int count = 0; и все ок...
Не понял. Здесь ты тоже явно указал инициализатор. Это тоже "явное действие человека". Чем этот вариант лучше, с твоей точки зрения, чем вариант с указанием инициализатора при определении переменной?
Кстати, для переменных целочисленных типов С++ тоже позволяет указывать инициализаторы при объявлении
struct T
{
static int count = 0;
...
};
int T::count;
Определение статического объекта (без инициализатора), если он используется в программе, при этом все равно надо делать. От этого в С++ никуда не уйдешь. (Правда, не совсем понятно, что рассматривается как "использование" объекта в программе).
А>Где-то читал, что все статические переменные и члены класса изначально инициализируются нулями. Эксперимент с доступными компиляторами это вроде подтверждает. Но, как я понимаю, это не оговорено стандартом и пользоваться этим нехорошо. Как быть?
Это оговорено стандартом.
Здравствуйте Андрей Тарасевич, Вы писали:
АТ>Определение статического объекта (без инициализатора), если он используется в программе, при этом все равно надо делать. От этого в С++ никуда не уйдешь. (Правда, не совсем понятно, что рассматривается как "использование" объекта в программе).
АТ>Это оговорено стандартом.
Вот что буквально говорит по этому поводу
Маэстро
So why do these inconvenient restrictions exist? 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. See D&E for an explanation of C++'s design tradeoffs.
...
You can take the address of a static member if (and only if) it has an out-of-class definition.