У меня в проекте есть несколько классов, объектов которых не должно быть больше одного. И чтобы не создавать очень похожий код в каждом классе, я использую такой шаблон:
И использовать это нужно так. В отдельном h-файле интерфейс используемого класса. Это чтобы не нужно было перекомпилировать все сурсы, использующие класс, при изменениях в нем. Реализация интерфейса класса получается очень простая.
class iClass1:
public iSingleton<iClass1>
{
public:
virtualvoid method1() = 0;
virtualvoid method2() = 0;
};
Ну и сам класс:
class cClass1:
public iClass1
{
public:
cClass1(){m_instance = this;}
virtualvoid method1(){}
virtualvoid method2(){}
private:
void method3(){}
void method4(){}
};
Во первых, бросая исключение в конструкторе вы создаете потенциальную утечку памяти. То есть объект который в своем конструторе выкинул исключение не считается сконструированным, и для него не будет вызван деструктор. Который, кстати было бы неплохо сделать виртуальным.
Во вторых вы не определили конструктор копирования, так что такой код вполне себе рабочий, и можно без проблем сделать вторую копию.
cClass1 c1;
cClass1 c2(c1);
В третьих использование такого синглтона крайне сомнительно, getInstance в вашем случае вернет нам не конечный класс, а интерфейс. А что если нам нужен доступ к полям конечного класса и его невиртуальным методам, а не только методам определенным в интерфейсе? А если у конечного класса вообще несколько интерфейсов, будете к каждому прикручивать синглтон сверху? (ну там ладно, можно и виртуально наследовать) и что если эти же интерфейсы нужны другим классам которые не являются синглтонами? Стоит овчинка выделки?
Паттерны не для того придумывали, что бы делать с ними такие извращения. Это уже не синглтон.
Ivaneo > То есть объект который в своем конструторе выкинул исключение не считается > сконструированным, и для него не будет вызван деструктор.
Разве конструктор Синглтона в данном случае не вызывается первым?
А раз так, то конструктор объекта (в котором предположительно и выделяется память) вообще не будет вызван...
class cClass1:
public iClass1
{
public:
cClass1(){m_instance = this;} // Вот так делать не хорошо...virtualvoid method1(){}
virtualvoid method2(){}
private:
void method3(){}
void method4(){}
};
Нужно наоборот избавляться от такого...
Автору советую посмотреть реализацию синглтонов из OGRE...
class System :
public Singleton<System>
{
public:
System(int argc, char* argv[])
{
}
~System()
{
}
int run()
{
return0;
}
};
int main(int argc, char* argv[])
{
int res;
new System(argc, argv);
res = System::getSingleton().run();
delete System::getSingletonPtr();
return res;
}
Ivaneo
> То есть объект который в своем конструторе выкинул исключение не считается сконструированным, и для него не будет вызван деструктор.
Зато будет вызван деструктор базового класса и деструкторы всех успешно созданных членов.