/*
10.4.9 Страуструп, специальное издание.
Переменная, определенная вне любой фунции, (то есть глобальная, объявленная в пространстве имен или статически в классе) инициализируется (конструируется) до вызова main.
..............................
Иногда при создании библиотеки необходимо или просто удобно изобрести тип с конструктором и деструктором, единственной целью которого является инициализация и последующая очистка.
*/
#include <iostream>
struct Zlib_init
{
Zlib_init() { std::cout <<"!"; }
~Zlib_init() { std::cout <<"?"; }
};
struct Zlib
{
static Zlib_init x;
};
Zlib_init Zlib::x;
int main()
{
}
Но вот в таком случае надо почему-то специально шаманить, что бы конструктор вызывался. Почему же?
#include <iostream>
#include <map>
class Object
{
public:
virtual ~Object() {}
};
//это на самом деле 16 байтовый GUID
typedef int TypeID;
typedef Object* (*CreateFuncT)();
template <class T> Object *Create() { return new T; }
//на самом деле это синглетон, который гарантирует, что type_registry
//при обращении к нему уже создан.
typedef std::map <TypeID, CreateFuncT> TypeIDMap;
TypeIDMap type_registry;
template <class T>
struct AutoRegister
{
AutoRegister()
{
//Вот этот конструктор нифига не выполняется !!!!!!!!!!!!!!!!!!!!!
//a тут на самом деле стоит проверка, не зарегистрирован ли уже этот type_id
type_registry.insert(
std::pair< TypeID, CreateFuncT >(T::class_type_id, &Create<T>));
std::cout <<"test, typeid == " << T::class_type_id;
}
};
Object *Fabric(TypeID type_id)
{
TypeIDMap::iterator iter= type_registry.find(type_id);
if (iter!= type_registry.end())
{
return iter->second();
}
else
{
std::cerr <<"sorry, can't find this typeid(" <<type_id <<")";
return 0;
}
}
template <class T>
struct AutoRegisterWithStaticMember
{
static AutoRegister<T> x;
};
template <class T>
AutoRegister<T> AutoRegisterWithStaticMember<T>::x;
#define CLASS_TYPE_ID(TYPE, TYPE_ID) \
enum { class_type_id= TYPE_ID }; \
struct AutoRegisterInnerStruct \
{ \
AutoRegisterWithStaticMember< TYPE > y; \
}; \
//а вот с таким шаманством он все-таки вызывает конструктор
/* void Shamanstvo() { AutoRegisterInnerStruct().y.x; } \ */
//------------------------------
// а здесь пользователи объявляют свои обекты
class MyObject1: public Object
{
public:
CLASS_TYPE_ID(MyObject1, 1+0*0x12345678);
};
class MyObject2: public Object
{
public:
CLASS_TYPE_ID(MyObject2, 2+0*0xDEADDEAD);
};
int main()
{
if (0)
{
//а вот с таким шаманством он все-таки вызывает конструктор
MyObject1::AutoRegisterInnerStruct t;
t.y.x;
}
//считываем из файла, какой объект надо создать
TypeID type_id;
std::cout <<"Enter type_id: ";
std::cin >>type_id;
Object *p_obj= Fabric(type_id);
}