Не вызывается конструктор static-члена
От: _Winnie Россия C++.freerun
Дата: 27.06.04 02:10
Оценка:
/*
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);
}
Правильно работающая программа — просто частный случай Undefined Behavior
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.