LINUX.ORG.RU

Как обычно создается синглтон: наследованием или прямым кодом?

 , singletone,


2

3

Нигде не нашел внятного ответа на простой вопрос.

В программе нужно иметь несколько синглтонов, например один из вариантов синглтона Майерса:

class CMySingleton
{
public:
  static CMySingleton& Instance()
  {
    static CMySingleton singleton;
    return singleton;
  }

// Other non-static member functions
private:
  CMySingleton() {}                                  // Private constructor
  ~CMySingleton() {}
  CMySingleton(const CMySingleton&);                 // Prevent copy-construction
  CMySingleton& operator=(const CMySingleton&);      // Prevent assignment
};

Как такие классы-синглтоны правильнее создавать? Просто надо наследоваться от вышеуказанного CMySingleton, или надо напрямую привести хидер обычного класса к такому же состоянию и прописать реализацию метода Instance()?

★★★★★

Просто надо наследоваться от вышеуказанного CMySingleton

Это не будет работать без шаблонов. Instance же должен создавать и возвращать правильный тип.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Это не будет работать без шаблонов. Instance же должен создавать и возвращать правильный тип.

Ну да, я это и хотел узнать. Как на практике делают? Создают базовый шаблонный класс, от него наследуются, прописывая нужный тип и не забыв про инициализацию нужного типа?

Или не парятся и вставляют реализацию Instance и поехали дальше?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от xaizek

А вот интересно, если в создающей статической функции будет следующий код, то как будет работать?:

static CMySingleton* singleton = new CMySingleton;
return *singleton;
rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 1)

если у тебя один синглтон (что чаще всего и есть), то можно просто написать один конечный класс. если тебе вдруг надо их несколько разных (что странно и маловероятно) - тогда можешь городить наследование.

Iron_Bug ★★★★★
()
Ответ на: комментарий от rumgot

если добавишь проверку, что инстанс создаётся единожды (обычно булевый флажок в приватных данных), то будет работать.

Iron_Bug ★★★★★
()
Ответ на: комментарий от rumgot

как будет работать?

В C++11 и выше инициализация статических переменных защищена от гонки. Будет работать так же, как и при static CMySingleton singleton;, через __cxa_guard_acquire/__cxa_guard_release. Только деструктор вызываться больше не будет.

i-rinat ★★★★★
()
Ответ на: комментарий от Iron_Bug

если добавишь проверку

Не нужна, начиная с C++11. Компилятор уже создаёт код для проверки.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Только деструктор вызываться больше не будет.

А, да. Это понимаю.

rumgot ★★★★★
()
Ответ на: комментарий от Iron_Bug

если у тебя один синглтон (что чаще всего и есть), то можно просто написать один конечный класс. если тебе вдруг надо их несколько разных (что странно и маловероятно) - тогда можешь городить наследование.

А почему синглтон должен быть один? У меня вот сколько кандидатов на синглтон:

* Фиксированные параметры программы
* Глобальные параметры программы (вычислимые на этапе инициализации, иногда меняющиеся в процессе выполнения программы)
* Конфигурация программы (считанная из файла конфигурации)
* Конфигурация хранилища данных
* Объект слежения за состоянием корзины
* История посещаемых записей
* Логгер действий с данными
* Менеджер горячих клавиш
* Периодические проверяторы

Или хочешь сказать, что все такие объекты надо собрать как свойства одного класса, обозвать его типа CoreItems, сделать его синглтоном и использовать?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

как тебе больше нравится. но многое из этого не имеет необходимости в синглтоне. сингтон - это блокирование, не забывай.

Iron_Bug ★★★★★
()

В 99% случаев singleton это акт отчаяния, за редкими и очень редкими исключениями.

По-поводу кода - как удобно так и реализовывай, принято везде по разному, вплоть до наличия приписки singleton или догадайся мол сама. Мне нравится как это сделано в бусте(CRTP), но это вкусовщина, хотя, в случае махровых плюсов - самый идиоматичный способ видимо.

pon4ik ★★★★★
()
Ответ на: комментарий от Iron_Bug

сингтон - это блокирование

Не понимаю тебя. Блокирование чего? Того, что объект создастся несколько раз? Так именно это и нужно от синглтона.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

если у тебя один синглтон
если тебе вдруг надо их несколько разных

А почему синглтон должен быть один?

ЛОР не перестаёт меня радовать и в этом году!

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

ЛОР не перестаёт меня радовать и в этом году!

Аж джва раза сообщил нам эту интересную информацию.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Просто не создавай больше одного экземпляра и всё.

Я и не создаю. Но у меня все эти экземпляры созданы в глобальной области видимости, потому что должны быть доступны везде, и на них статический анализатор ругается:

main.cpp:44:17: warning: no previous extern declaration for non-static variable 'fixedParameters'

Вот я и думаю, как правильнее это исправить.

У меня есть еще вариант: сделать расширеннй класс QApplication, и в него понапихать все эти объекты.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Не должен, он же ругается на отсутствия явного указания видимости, а здесь extern добавили.

Городить синглтоны, чтобы убрать такие предупреждения, лишнее. Если переделывать этот код, то уже сразу на создание классов где-то в главном объекте и передачу их дальше по коду или что-то в этом роде.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Не должен, он же ругается на отсутствия явного указания видимости, а здесь extern добавили.

Extern тут не при чем. Ругаться будет в b.cpp на строку создания объекта «b a;». А если сделать «static b a;», тогда через extern в a.h объект a не будет находиться, примерно с такой ошибкой:

undefined reference to `a'

Если переделывать этот код, то уже сразу на создание классов где-то в главном объекте и передачу их дальше по коду или что-то в этом роде.

Ну вот видимо придется все в производный от QApplication класс засовывать.

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от Xintrea

Ошибка явно говорит о «no previous extern declaration for non-static variable». Так что при чём.

xaizek ★★★★★
()
Ответ на: комментарий от deep-purple

не создавай больше одного экземпляра и всё

Да да, синглтоны говно, используйте глобальные переменные господа! Чёт ржу.

no-such-file ★★★★★
()
Ответ на: комментарий от Xintrea

Я обычно конфиги, логгеры и прочее действительно собираю в главном Application (и кстати удобно макрос иметь типа как qApp, только static_cast в твой класс).

fluorite ★★★★★
()
Последнее исправление: fluorite (всего исправлений: 1)
Ответ на: комментарий от Xintrea

экземпляры созданы в глобальной области видимости

Детский сад просто. Должен быть proxy, который направляет запрос на нужный экземпляр сервиса.

Liz812
()
Ответ на: комментарий от rumgot

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

Liz812
()
Ответ на: комментарий от rumgot

Unit тесты с синглтонами видел? Я - видел, это не unit тесты

Begemoth ★★★★★
()
Ответ на: комментарий от Liz812

Это какая-то аксиома из учебника? Почему это приводит к массе ошибок?

Вот нужно мне в нескольких классах ссылка на некий другой класс (объект класса, ок). Тут можно всем этим классам в конструкторе передовать эту ссылку и хранить ее. Или же можно получать доступ через синглтон. Чем это плохо?

rumgot ★★★★★
()
Ответ на: комментарий от rumgot

Не угодили не одиночки, а то, что каждый новоиспечённый аркутехтор норовит применить своё знание шаблонов проектирования и начинает с самых простых. А то, что они реже всего нужны, их не останавливает, у них уже в руках молот, а вокруг значится всё - гвозди.

pon4ik ★★★★★
()
Ответ на: комментарий от no-such-file

используйте глобальные переменные

Есть куча способов этого не делать.

синглтоны говно

А где я такое сказал?

Так то, скажу что каждой хрени своё применение, и ты согласишься.

Но ... зачем ему тут именно синглтон?

deep-purple ★★★★★
()
Ответ на: комментарий от rumgot

Получая ссылку на объект ты можешь изменить состояние из 100 разных мест. А если в него лезут из разных потоков то он должен уметь сериализацию, а это значит он должен делать некоторые предположения от том что вне его. Протечка абстракции и нарушение принципа единичной ответственности.

Liz812
()
Ответ на: комментарий от Liz812

он должен уметь сериализацию

В первую очередь он должен иметь правильный интерфейс, чтобы не провоцировать гонки

Begemoth ★★★★★
()
Ответ на: комментарий от Xintrea

У тебя большие проблемы с дизайном, все твои синглтоны — ни что иное как глобальные переменные, но в соусе. Счастливого юнит-тестирования!

По-нормальному это делается через компоненты с явным их связыванием, по желаю с депенденси инъекциями.

filosofia
()
Ответ на: комментарий от filosofia

с вашим юнит- и вообще тестированием большие проблемы - оно заставляет изголяться и выкручиваться архитектурно исключительно в его угоду.

нет, я не хейтю, но подумай об этом.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Так юнит тестирование в данном случае лишь показывает, как хреново спроектированная программа тяжела для модификации и переработки. Вроде и на компоненты все разбито, а взять и пересвязать их невозможно. Почему? Потому что синглтоны — жирнющее глобальное состояние-клей.

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

filosofia
()
Ответ на: комментарий от Liz812

А если в него лезут из разных потоков то он должен уметь сериализацию

Это почему?

rumgot ★★★★★
()
Ответ на: комментарий от filosofia

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

тестирование не ограничивается юнит-тестами

seiken ★★★★★
()
Ответ на: комментарий от Begemoth

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

peregrine ★★★★★
()
Ответ на: комментарий от Xintrea

Логгер действий с данными

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

peregrine ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.