Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

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

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

Ответ
 
Опции темы
Старый 15.06.2017, 21:52   #1
Aoizora
Заблокирован
 
Регистрация: 11.11.2016
Сообщений: 262
Репутация: 109
По умолчанию Синглтон Майерса и 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, 23:37   #2
waleri
Профессионал
 
Регистрация: 13.07.2012
Адрес: Нижний Новгород
Сообщений: 5,431
Репутация: 1667
По умолчанию

Код:

CSomeClass& GetInstance(...)
{
  static CSomeClass* ptr;
  if (0 == ptr) ptr = new CSomeClass(...);
  return *ptr;
}

waleri вне форума   Ответить с цитированием
Старый 16.06.2017, 07:10   #3
Croessmah
Вредный кошак
Профессионал
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Адрес: г. Инза
Сообщений: 1,155
Репутация: 379
По умолчанию

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

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

Цитата:
Сообщение от 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 в 13:08.
alexzk вне форума   Ответить с цитированием
Старый 19.06.2017, 13:11   #6
alexzk
Участник клуба
 
Регистрация: 12.04.2017
Сообщений: 889
Репутация: 172
По умолчанию

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

Код:

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, 13:16   #7
Aoizora
Заблокирован
 
Регистрация: 11.11.2016
Сообщений: 262
Репутация: 109
По умолчанию

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

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

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

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

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

inline + static
+static
static+static

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

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

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


10:55.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru