Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.06.2017, 20:52   #1
Aoizora
Заблокирован
 
Регистрация: 11.11.2016
Сообщений: 261
По умолчанию Синглтон Майерса и getInstance с параметром

Есть такой класс для управления соединением с БД:

Код:
class connection
{
	friend void query(const connection & _conn,
                      const std::string & _query);
	using handle = sqlite3 *;
public:
	static connection & connect(const std::string & _dbfile);
	static handle get();

protected:
	connection(const std::string & _dbfile);
	connection(const connection & _conn)             = default;
	connection & operator=(const connection & _conn) = default;
	virtual ~connection()                            = default;

	static connection * conn;
	static handle db_handle;
};
Я пытаюсь реализовать синглтон Майерса, потому что мне нужно передавать соединение по ссылке, а не по указателю. Ключевая часть реализации здесь:

Код:
connection & connection::connect(const std::string & _dbfile)
{
	static connection c(_dbfile);
	return c;
    /*if (conn == nullptr)
    {
        conn = new connection(_dbfile);
    }
    return conn;*/
}
Стандартный синглтон, но в нем есть проблема: поскольку в функцию connect передается название БД, статическая переменная будет перезаписываться при каждом вызове, а это противоречит назначению синглтона - управлять одним и тем же ресурсом.

Как можно возвращать ссылку, и в то же время не перезаписывать переменную?
Aoizora вне форума Ответить с цитированием
Старый 15.06.2017, 22:37   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Код:
CSomeClass& GetInstance(...)
{
  static CSomeClass* ptr;
  if (0 == ptr) ptr = new CSomeClass(...);
  return *ptr;
}
waleri вне форума Ответить с цитированием
Старый 16.06.2017, 06:10   #3
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Статическая переменная будет инициализирована при первом вызове данной функции. Остальные вызовы никак её не поменяют. Плюс ко всему, такое создание синглтона будет потокобезопасно.
Croessmah вне форума Ответить с цитированием
Старый 18.06.2017, 17:07   #4
Aoizora
Заблокирован
 
Регистрация: 11.11.2016
Сообщений: 261
По умолчанию

Несмотря на то, что во всех примерах синглтона возвращается указатель или ссылка на сам синглтон, я могу вернуть что угодно. Могу ли я возвращать хэндл БД при вызове connect и не будет ли это нарушением паттерна?
Aoizora вне форума Ответить с цитированием
Старый 19.06.2017, 12:04   #5
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Код:
CSomeClass& GetInstance(...)
{
  static CSomeClass* ptr;
  if (0 == ptr) ptr = new CSomeClass(...);
  return *ptr;
}
удалить же забыли...тогда нада std::shared_ptr, компилер почистит по выходу из программы.

мелочи-мелочи, а такие вещи, даже на java, в андроиде жуть че творят. Хотя казалось бы ... автоматом вся память - а нет - статик живет, пока живет ВМ, а вм живет - для ускорения запуска - и начинается свистопляска (а если вставите в дроид С++ код такой - то там ток ребут).

Вообще я так делаю в хидере - тоже инит при первом использовании:

Код:
inline SomeClass& func()
{
    static SomeClass a;
    return a;
}

Последний раз редактировалось alexzk; 19.06.2017 в 12:08.
alexzk вне форума Ответить с цитированием
Старый 19.06.2017, 12:11   #6
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Вот еще пример, хидер:

Код:
template <class T>
inline T& globalInstance()
{
    static T inst;
    return inst;
}

template <class T>
const inline T& globalInstanceConst()
{
    static const T inst;
    return inst;
}

//if this class is sublassed it allows to create only 1 instance of the child at runtime

template <class T>
class ThereisOnlyOne
{
private:
    T* dumb; //template ensures compiler will generate different statics for each T
    std::atomic_flag& lock()
    {
        static std::atomic_flag locked = ATOMIC_FLAG_INIT;
        return locked;
    }

protected:
    ThereisOnlyOne() :
        dumb(nullptr)
    {
        if (lock().test_and_set())
        {
            std::string s = "Second instance of " + std::string(typeid(T).name())+" is not allowed.";
            FATAL_RISE(s);
        }
    }
    virtual ~ThereisOnlyOne()
    {
        lock().clear();
    }
};

Где-то совсем потом:

Код:
class A : public B, public ThereisOnlyOne<A>
{
};
Получение инстанса:

globalInstance<A>()
alexzk вне форума Ответить с цитированием
Старый 19.06.2017, 12:16   #7
Aoizora
Заблокирован
 
Регистрация: 11.11.2016
Сообщений: 261
По умолчанию

Еще для использования RAII при работе с БД можно применять std::unique_ptr с пользовательским деструктором, а для удобного для чтения создания такого указателя можно написать шаблонную функцию. Но такой указатель не будет глобальным. Что лучше: указатель или синглтон?
Aoizora вне форума Ответить с цитированием
Старый 19.06.2017, 12:18   #8
Aoizora
Заблокирован
 
Регистрация: 11.11.2016
Сообщений: 261
По умолчанию

Для чего используется inline? Темплейты по умолчанию и так inline.
Aoizora вне форума Ответить с цитированием
Старый 19.06.2017, 12:20   #9
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

У
Цитата:
Сообщение от Aoizora Посмотреть сообщение
Еще для использования RAII при работе с БД можно применять std::unique_ptr с пользовательским деструктором, а для удобного для чтения создания такого указателя можно написать шаблонную функцию. Но такой указатель не будет глобальным. Что лучше: указатель или синглтон?
Указатель, с кастомным удалятором. Но, кажется, unique_ptr не позволяет его задать. Тогда нужен класс-обвертка, который при удалении освободит ресурс. Напрямую хэндлы ресурса совать в указатель - очень плохая идея.
alexzk вне форума Ответить с цитированием
Старый 19.06.2017, 12:21   #10
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Aoizora Посмотреть сообщение
Для чего используется inline? Темплейты по умолчанию и так inline.
По привычке. Остатки копипаста - сначало это был конкретный класс, а потом стал темплейтом.
Вобщем оно не мешает там.

...а стоп, по-моему как раз там inline нужен. Связано это с тем, как компилятор генерит статик мембер. Там комбинаций много

inline + static
+static
static+static

вобщем для уверенности, я прописал как мне нада.
alexzk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Синглтон и паттерн. Что это такое и с чем его едят? (C#)) max_prorok Общие вопросы по программированию, компьютерный форум 21 22.03.2016 14:59
Запрос с параметром Claster Помощь студентам 0 11.06.2012 11:44
Синглтон. Исключение при вызове метода через глобальную точку доступа. clions C# (си шарп) 3 13.04.2012 21:09
Цикл с параметром Гузеля Паскаль, Turbo Pascal, PascalABC.NET 2 21.03.2012 20:59
Синглтон megachuhancer Общие вопросы Delphi 0 11.05.2010 13:23