Привет!
Вопрос, быть может, дурацкий, но как избежать многократного вызова констуктора глобально объекта. В файле cont.h объявлено:
typedef class _CONTAINER{
} CCONTAINER;
// нижеstatic CCONTAINER container;
Я думал, что объявив глобальный объект с помощью static, я добьюсь того, что конструктор будет вызван единожды. Ан нет! Конструктор вызывается столько раз, сколько раз в программе встречается #include "cont.h". Как я должен описать объект, чтобы конструктор был вызван однажды?
З.Ы. @pragma once почему-то использовать не хочется.
Спасибо!
Re: многократный вызов конструктора глобального объекта
Здравствуйте, andsin, Вы писали:
A>Привет! A>Вопрос, быть может, дурацкий, но как избежать многократного вызова констуктора глобально объекта. В файле cont.h объявлено: A>
A>typedef class _CONTAINER{
A>} CCONTAINER;
A>// ниже
A>static CCONTAINER container;
A>
Здравствуйте, andsin, Вы писали:
A>Привет! A>Вопрос, быть может, дурацкий, но как избежать многократного вызова констуктора глобально объекта. В файле cont.h объявлено: A>
A>typedef class _CONTAINER{
A>} CCONTAINER;
A>// ниже
A>static CCONTAINER container;
A>
A>Я думал, что объявив глобальный объект с помощью static, я добьюсь того, что конструктор будет вызван единожды. Ан нет! Конструктор вызывается столько раз, сколько раз в программе встречается #include "cont.h". Как я должен описать объект, чтобы конструктор был вызван однажды? A>З.Ы. @pragma once почему-то использовать не хочется. A>Спасибо!
// В файле file1.cpp
Foo foo;
Foo* f = &foo;
// В файле file2.cppextern Foo* f;
Foo f1(*f); // Используется конструктор копий
Если бы все это находилось в одном исходном файле, ситуация была бы нормальной. Со строкой Fоо*
f = &foo; проблем не возникает, поскольку глобальные объекты одного исходного файла заведомо
(хе-хе) инициализируются в порядке их определения. Другими словами, когда программа доберется до
этой строки, объект foo уже будет сконструирован. Тем не менее, никто не гарантирует, что
глобальные объекты в файле file1.cpp будут инициализированы раньше глобальных объектов в файле
file2.срр. Если file2.cpp будет обрабатываться первым, f оказывается равным 0 (NULL на большинстве
компьютеров), и при попытке получить по нему объект ваша программа героически умрет.
Лучший выход — сделать так, чтобы программа не рассчитывала на конкретный порядок
инициализации файлов .срр. Для этого используется стандартный прием — в заголовочном файле .h
определяется глобальный объект со статической переменной, содержащей количество
инициализированных файлов .срр. При переходе от 0 к 1 вызывается функция, которая инициализирует
все глобальные объекты библиотечного файла .срр. При переходе от 1 к 0 все объекты этого файла
уничтожаются.
К этому нужно привыкнуть. А происходит следующее: файл .h компилируется со множеством других
файлов .срр, один из которых — Library.cpp. Порядок инициализации глобальных объектов,
встречающихся в этих файлах, предсказать невозможно. Тем не менее, каждый из них будет иметь
свою статическую копию LibraryDummy. При каждой инициализации файла .срр, в который включен
файл Library.h, конструктор LibraryDummy увеличивает счетчик. При выходе из main() или при
вызове exit() файлы .срр уничтожают глобальные объекты и уменьшают счетчик в деструкторе
LibraryDummy. Конструктор и деструктор гарантируют, что OpenLibrary() и CloseLibrary()
будут вызваны ровно один раз.
-=Джефф Элджер=- C++ for real programmer
Re: многократный вызов конструктора глобального объекта
Здравствуйте, andsin, Вы писали:
A>Привет! A>Вопрос, быть может, дурацкий, но как избежать многократного вызова констуктора глобально объекта. В файле cont.h объявлено: A>
A>typedef class _CONTAINER{
A>} CCONTAINER;
A>// ниже
A>static CCONTAINER container;
A>
A>Я думал, что объявив глобальный объект с помощью static, я добьюсь того, что конструктор будет вызван единожды. Ан нет! Конструктор вызывается столько раз, сколько раз в программе встречается #include "cont.h". Как я должен описать объект, чтобы конструктор был вызван однажды? A>З.Ы. @pragma once почему-то использовать не хочется. A>Спасибо!
1. в хидере объявлять переменные нестоит, для этого воспользуйтесь extern;
2. Обязательно заключайте содержимое хидера в:
#ifndef ...
#define ...
#endif
3. Ну а собственно в .сср уже и объявляейте статический объект
Вот пример кода: Abra.h Он и содержит требуемый объек
J>Вооля...сколько раз не подключай...больше одного раза конструктор не вызоветься (как не проси )
Только вот static тут ставить не надо.
Re: многократный вызов конструктора глобального объекта
От:
Аноним
Дата:
06.07.04 18:50
Оценка:
A>Я думал, что объявив глобальный объект с помощью static, я добьюсь того, что конструктор будет вызван единожды.
Как раз наоборот. Объявив его static ты делаешь его локальным, благодаря чему их создается столько, сколько у тебя файлов в которые он включается. А без static тебя бы обругал линкер за множественное определение одноименных переменных.
Re[2]: многократный вызов конструктора глобального объекта
struct GlobalInitializer {
GlobalInitializer() { Initializer::Init(); }
~GlobalInitializer() { Initializer::Terminate(); }
};
int main() {
GlobalInitializer globalInitializer;
// start your program here
}
надеюсь, суть понятна, использовать крайне просто,
в любой единице трансляции создаете по месту статический екземпляр класса-наследника Initializer, с переопределенными OnInit() и OnTerminate().
-------
когда я это использовал?
тогда, когда конструкторы статических объектов начинают использовать статические экземпляры друг-друга (например — авторегистрация в каком-нить динамическом массиве, а тот, хе-хе, не готов еще...)
так вот, всю подобную логику из конструктора вынести, и в инициализатор внести.
технология крайне гибкая, вплоть до того, что можно по месту создавать класс-гибрид целевого класса и инициализатора:
static struct : public TargetClass, public Initializer {
[...]
virtual void OnInit() {
// do some initialization...
// use another static objects from different units
}
[...]
} myStaticExemplarOfTargetClass;
успехов.
Re: многократный вызов конструктора глобального объекта
Re[2]: многократный вызов конструктора глобального объекта
От:
Аноним
Дата:
07.07.04 12:12
Оценка:
Здравствуйте, andsin, Вы писали:
A>Большое спасибо! Полная ясность!
Остался невыясненный случай, когда один статический объект ссылается на другой. Ок, теперь у нас onInit() ссылается, не конструктор. И точно также ссылается на объект, чей onInit еще не вызвался. Те же яйца только в профиль.