Простой интерфейс для классов-синглтонов (комментарии)
Это сообщение сгенерировано автоматически.
Во первых, бросая исключение в конструкторе вы создаете потенциальную утечку памяти. То есть объект который в своем конструторе выкинул исключение не считается сконструированным, и для него не будет вызван деструктор. Который, кстати было бы неплохо сделать виртуальным.
Во вторых вы не определили конструктор копирования, так что такой код вполне себе рабочий, и можно без проблем сделать вторую копию.
cClass1 c1;
cClass1 c2(c1);
В третьих использование такого синглтона крайне сомнительно, getInstance в вашем случае вернет нам не конечный класс, а интерфейс. А что если нам нужен доступ к полям конечного класса и его невиртуальным методам, а не только методам определенным в интерфейсе? А если у конечного класса вообще несколько интерфейсов, будете к каждому прикручивать синглтон сверху? (ну там ладно, можно и виртуально наследовать) и что если эти же интерфейсы нужны другим классам которые не являются синглтонами? Стоит овчинка выделки?
Паттерны не для того придумывали, что бы делать с ними такие извращения. Это уже не синглтон.
Ivaneo
> То есть объект который в своем конструторе выкинул исключение не считается
> сконструированным, и для него не будет вызван деструктор.
Разве конструктор Синглтона в данном случае не вызывается первым?
А раз так, то конструктор объекта (в котором предположительно и выделяется память) вообще не будет вызван...
novice
class cClass1: public iClass1 { public: cClass1(){m_instance = this;} // Вот так делать не хорошо... virtual void method1( ){} virtual void method2( ){} private: void method3( ){} void method4( ){} };
Нужно наоборот избавляться от такого...
Автору советую посмотреть реализацию синглтонов из OGRE...
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
> То есть объект который в своем конструторе выкинул исключение не считается сконструированным, и для него не будет вызван деструктор.
Зато будет вызван деструктор базового класса и деструкторы всех успешно созданных членов.
ezhickovich
> Автору советую посмотреть реализацию синглтонов из OGRE...
Лучше сразу начать читать Александреску.
_zerg_
> > Автору советую посмотреть реализацию синглтонов из OGRE...
> Лучше сразу начать читать Александреску.
Александреску имеет отношение к OGRE ? :)
#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);
innuendo
> Александреску имеет отношение к OGRE ? :)
Но он явно имеет отношение к синглетонам =)
Igor'
> Igor'
Жесть!
Синглетон - это
extern CSome *g_pSome;
я обычно так делаю синглтоны
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;
Конструктор надо бы пометить, что он кидает исключение.
Тема в архиве.