Войти
ПрограммированиеФорумОбщее

Простой интерфейс для классов-синглтонов (комментарии)

#0
8:33, 27 июня 2011

Простой интерфейс для классов-синглтонов (комментарии)

Это сообщение сгенерировано автоматически.

#1
8:33, 27 июня 2011

Во первых, бросая исключение в конструкторе вы создаете потенциальную утечку памяти. То есть объект который в своем конструторе выкинул исключение не считается сконструированным, и для него не будет вызван деструктор. Который, кстати было бы неплохо сделать виртуальным.
Во вторых вы не определили конструктор копирования, так что такой код вполне себе рабочий, и можно без проблем сделать вторую копию.
cClass1 c1;
cClass1 c2(c1);

В третьих использование такого синглтона крайне сомнительно, getInstance в вашем случае вернет нам не конечный класс, а интерфейс. А что если нам нужен доступ к полям конечного класса и его невиртуальным методам, а не только методам определенным в интерфейсе? А если у конечного класса вообще несколько интерфейсов, будете к каждому прикручивать синглтон сверху? (ну там ладно, можно и виртуально наследовать) и что если эти же интерфейсы нужны другим классам которые не являются синглтонами? Стоит овчинка выделки?

Паттерны не для того придумывали, что бы делать с ними такие извращения. Это уже не синглтон.

#2
9:20, 27 июня 2011

Ivaneo
> То есть объект который в своем конструторе выкинул исключение не считается
> сконструированным, и для него не будет вызван деструктор.
Разве конструктор Синглтона в данном случае не вызывается первым?
А раз так, то конструктор объекта (в котором предположительно и выделяется память) вообще не будет вызван...

#3
9:28, 27 июня 2011

novice

class cClass1:
    public iClass1
{
public:
    cClass1(){m_instance = this;} // Вот так делать не хорошо...
    virtual void method1(){}   
    virtual void method2(){}   
private:
    void method3(){}
    void method4(){}
};

Нужно наоборот избавляться от такого...

Автору советую посмотреть реализацию синглтонов из OGRE...

#4
9:29, 27 июня 2011

novice

Как уже сказал Ivaneo, это плохой синглетон. Хороший синглетон выглядит примерно так:

template<class T>
class Singleton
{
public:
  Singleton(void)
  {
    assert(singleton == 0);
    singleton = static_cast<T*>(this);
  }

  virtual ~Singleton(void)
  {
    singleton = 0;
  }
public:
  static T& getSingleton()
  {
    assert(singleton);
    return *singleton;
  }

  static T* getSingletonPtr()
  {
    return singleton;
  }

protected:
  static T* singleton;
};

template<class T>
T* Singleton<T>::singleton = 0;

Пример:

class System :
  public Singleton<System>
{
public:
  System(int argc, char* argv[])
  {
  }

  ~System()
  {
  }

  int run()
  {
    return 0;
  }
};

int main(int argc, char* argv[])
{
  int res;

  new System(argc, argv);

  res = System::getSingleton().run();

  delete System::getSingletonPtr();

  return res;
}

Ivaneo

> То есть объект который в своем конструторе выкинул исключение не считается сконструированным, и для него не будет вызван деструктор.
Зато будет вызван деструктор базового класса и деструкторы всех успешно созданных членов.

#5
9:45, 27 июня 2011

ezhickovich
> Автору советую посмотреть реализацию синглтонов из OGRE...
Лучше сразу начать читать Александреску.

#6
11:20, 27 июня 2011

_zerg_
> > Автору советую посмотреть реализацию синглтонов из OGRE...
> Лучше сразу начать читать Александреску.

Александреску имеет отношение к OGRE ? :)

#7
11:27, 27 июня 2011
  #define SINGLETON_BASE(Type)              \
    class Singleton##Type##Base {         \
    public:                               \
      Singleton##Type##Base();          \
      virtual ~Singleton##Type##Base(); \
    };                                    \

  #define SINGLETON_BASE_OF(Type ) Singleton##Type##Base

  #define SINGLETON_DECL(Type) \
    static Type* getInstancePtr(); \
    static Type& getInstance();    \

  #define SINGLETON_IMPL(Type) \
    Type* t##Type##instance = NULL; \
    Singleton##Type##Base::Singleton##Type##Base() { \
      t##Type##instance = static_cast<Type*>(this); \
    } \
    Singleton##Type##Base::~Singleton##Type##Base() { \
      t##Type##instance = NULL; \
    } \
    Type& Type::getInstance() { \
      return (*t##Type##instance); \
    } \
    Type* Type::getInstancePtr() { \
      return t##Type##instance; \
    } \

  #define SINGLETON_CONSTRUCT(Type) \
    if( t##Type##instance == NULL ) t##Type##instance = new Type(); \

  #define SINGLETON_OF(Type) t##Type##instance
}

.h

SINGLETON_BASE(Foo)
class Foo : public SINGLETON_BASE_OF(Foo) {
public:
    SINGLETON_DECL(Foo);
};

.cpp

SINGLETON_IMPL(Foo);
#8
11:30, 27 июня 2011

innuendo
> Александреску имеет отношение к OGRE ? :)
Но он явно имеет отношение к синглетонам =)

#9
11:30, 27 июня 2011

Igor'
> Igor'
Жесть!

#10
12:01, 27 июня 2011

Синглетон - это

extern CSome *g_pSome;
#11
11:56, 7 июля 2011

я обычно так делаю синглтоны

template<typename C> class Singleton
{
protected:

   static C* _instance;

   Singleton(void)
   {
   }

   Singleton(const Singleton& singleton)
   {
   }

   virtual ~Singleton(void)
   {
   }

   const Singleton& operator = (const Singleton& singleton)
   {
      return *this;
   }

public:

   static Singleton* instance(void)
   {
      if (_instance == NULL)
      {
         _instance = new C;
      }

      return _instance;
   }
};

template<typename C> C* Singleton<C>::_instance = NULL;
#12
12:29, 7 июля 2011

Конструктор надо бы пометить, что он кидает исключение.

ПрограммированиеФорумОбщее

Тема в архиве.