[C++] Написать Singleton

Sanjaz

Как написать сабж?

mirt1971

Ну например так:
A& getSingleton
{
static A a;
return a;
}

bobby

в .h:

class Singleton
{
private:
static Singleton * _instance;
Singleton;
public:
static Singleton * Instance { return _instance ? _instance : _instance = new Singleton; }
};


инициализируешь _instance нулем в .cpp:

Singleton * Singleton::_instance = 0;

Sanjaz

А можно написать так:?


class Singleton
{
static Singleton* instance(NULL);
Singleton* GetInstance
{
if (instance==NULL)
{
instance=new Singleton;
}
return instance;
}
};

mirt1971

Конечно можно. Это практически одно и то же(ну не учитывая что во втором случае тебе придется его самому удалять)

bobby

GetInstance должен быть вообще тоже static.

Sanjaz

А статические переменные можно так инициализировать?
static Singleton* instance(NULL)

bobby

по-моему, нет
хз

mirt1971

Можно.
bla blablabla
{
static Singleton* instance = 0;
}

Sanjaz

А как тогда узнать, есть ли объект, если нельзя указатель инициализировать NULL?

bobby

он про статические переменные класса, имхо.
в классе нельзя.

bobby

надо писать вне объявления класса:
Singleton * Singleton::_instance = 0;
(как будто это просто глобальная переменная)

mirt1971

А вообще советую почитать Андрея Александреску Modern C++ Design. Очень полезная книга.

Sanjaz

как инициализировать статические члены класса?

bobby

ваще я уже написал, даже два раза
в моем первом посте тоже написано

Sanjaz

Все понятно.
Всем спасибо.

mirt1971

Ну ваш пример можно(и нужно) переписать так:
.....
Singleton* Singleton::getInstance
{
static Singleton* i = 0;
if ( !i )
i = new Singleton;

return i;
}

bobby

почему нужно-то? =)

mirt1971

А зачем держать в классе ссылку на экземпляр этого же класса? Это наводит на подозрение Имхо просто красивее и компактнее получается.

bobby

не знаю, меня не наводит =)
соб-сно, если объект класса будет только один, почему бы в классе и не держать на него указатель?
вот.

mirt1971

В общем это дело вкуса. Но ты же там будешь держать еще и другие данные... Это все перемешается... Ну не знаю. Не нравится мне это

bobby

хз

myrka68

полностью солидарен с мадкрозом!

Dasar

такие static переменные лучше объявлять внутри функции.
В этом случае упрощается использование таких объявлений, т.к. при этом можно включать данное объявление произвольное число раз (от 0 до бесконечности).
При объявление static переменной в виде члена класса - приходится постоянно контролировать, чтобы мы переменные проинициализировали ровно один раз (не забыли вообще ее объявить, и не объявили ее два раза)

RTYuPZ78

также полезно добавить синглетон-убийцу
и что-то типа synchronized на getInstance

freezer

а деструктор кто будет вызывать?

freezer

можешь полный код привести?

mirt1971

Я же уже писал:
Singleton* Singleton::getInstance
{
static Singleton* i = 0;
if ( !i )
i = new Singleton;

return i;
}

mirt1971

Это не всегда обязательно.

freezer

а иногда бывает нужно. Например, log-файл закрыть и т.п.
Кстати, предыдущее сообщения я не тебе писал

mirt1971

Ну когда нужно, в конце программы пишешь delete Singleton::getInstance;
Ну и что из того что ты не мне писал? Тебе интересен ответ на вопрос или кто тебе ответит?

freezer

1. Ну да, т.е. я должен помнить где и когда создаются какие синглетоны, удалять их все на выходе...
Кстати, синглетон может быть инкапсулирован в другой библиотечке и быть нивидим на уровне функции main (или ее аналога). В то же время для глобальных объектов может автоматически вызываться деструктор, а ты эту возможность игнорируешь...
Еще такой момент: получается, что синглетон может быть запросто удален в любом месте... тоже нехорошо, после такого удаления с ним уже не поработаешь.
2. Я хотел услышать вариант ответа от конкретного человека

mirt1971

1.
а) lib_init lib_done - обычно во многих либах есть такое
б) Не игнорирую. Хотя и несколько по другому. Вот мой первый вариант в этом треде:
A& getSingleton
{
static A a;
return a;
}
2. Если не секрет, то почему именно от конкретного человека? Просто мне это кажется несколько странным

freezer

а) Так принято в Си-шных библиотеках, а в библиотеках Си++ без этого можно обойтись
б) Вообще-то "синглтон" - это класс у которого может быть только 1 объект. То что ты написал не подходит по определению

Dasar

Если деструктор не нужен и не нужна управляемая инициализация, то:


static MySingleton* GetSingleton
{
static MySingleton * singleton = new MySingleton;
return singleton;
}


С управляемой инициализацией:


static MySingleton * GetSingleton
{
static MySingleton * singleton = 0;
if (singleton == 0)
{
InitЧто-тоВажное;
singleton = CreateSingleton;
}
return singleton;
}


внешнее управление инициализацией и удалением


public: static void Init
{
getStorage = new MySingleton;
}
public: static void Done
{
getStorage = 0;
}
public: static MySingleton * GetSingleton
{
return getStorage;
}
protected: static MySingleton* & getStorage
{
static MySingleton * singleton = 0;
return singleton;
}

rosali

По-моему вот так писать самое правильное:

A& f
{
static A a;
return a;
}

Во-первых, объект будет создан при первом вызове f, это помогает (хотя и не всегда) избежать "гонок" при инициализации. В этом смысле static член класса хуже.
Во-вторых, объект будет (автоматически) удален, если был создан. В этом смысле вариант с new хуже.

rosali

Ну когда нужно, в конце программы пишешь delete

А где, простите, конец программы? Внизу main? А если этот объект нужен в деструкторе какой-то локальной для main переменной? Или в деструкторе статического объекта?

RTYuPZ78

SingletonKiller - должен быть отдельным классом

maksi-frid

Прикольно...
Юзал все это на работе в одном проекте и только сейчас узнал, что называется синглтон. Реализацию придумал сам.
Удалять можно в деструкторе, используя подсчет ссылок на объект.
стандартный AddRef, Release.
Оставить комментарий
Имя или ник:
Комментарий: