С++ - класс Singleton
Можно ли наследовать одноэлементный класс.
Если да,
то как мы можем это сделать?
** EDIT: *** Я хочу сказать, что если у нас есть класс, который использует шаблон дизайна singleton, то может ли он быть унаследован? *
Ответы
Ответ 1
singleton имеет частный конструктор, поэтому наследование невозможно. кроме того, у singleton есть статические методы для создания экземпляра частного экземпляра, и поскольку вы не можете переопределять статические методы, было бы бессмысленно наследовать от singleton.
Ответ 2
Это зависит от того, как ваша реализация для шаблона проектирования. Простейшей формой является создание такого класса:
class MySingleton
{
public:
static MySingleton &getInstance()
{
static MySingleton instance;
return instance;
}
private:
MySingleton();
~MySingleton();
};
В этом случае он не может быть унаследован, потому что производный класс не имеет доступа к его конструктору. Вы можете сделать конструктор защищенным, но это позволит другим производным классам быть не одиночными по желанию, что может быть беспорядочным с точки зрения дизайна. Но обычно эта простая форма не является предпочтительным способом реализации синглетонов, так как у вас нет большого контроля над ее временем жизни, и трудно правильно обрабатывать зависимости между синглтонами - не говоря уже о возможных проблемах многопоточности. Книга Современный дизайн на С++ (http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315/ref = sr_1_1? Ie = UTF8 & s = books & qid = 1270652521), среди прочих, имеет лучшие реализации; они основаны на шаблонах, а создание экземпляра шаблона делает объект одиночным (и его параметр является классом, который будет сделан одиночным). Это облегчает выполнение того, что вы хотите, поскольку "singleton-ness" отделен от самого класса. Но, тем не менее, я думаю, вам понадобится некоторая политика (возможно, введенная в действие кодом), чтобы избежать того, что какой-то класс, полученный из одноэлементного, будет не одиночным, что трудно реализовать.
Моя рекомендация состояла бы в том, чтобы иметь абстрактные базовые классы в качестве предков для ваших синглтонов и вносить в них поведение commom, а не в одиночном одиночном режиме, и иметь singleton всегда как "конечный" класс (заимствуя это значение из Java).
Ответ 3
Синглтонные классы должны быть унаследованы. Шаблон singleton не имеет большого значения без наследования.
- Определить в основном абстрактный базовый класс со статической функцией
instance()
.
- Определите один или несколько производных классов, реализующих базовый интерфейс.
- Внедрите
instance()
, чтобы решить во время выполнения, какой класс должен быть создан и возвращен.
Ответ 4
У меня есть класс Singleton, который я наследую во многих случаях.
Вот Синглтон:
template <class Target>
class Singleton_Shared_Ptr
{
//---------------------------------------------------------------------
// Public Constructors & Destructors
//---------------------------------------------------------------------
public:
//! Destructor.
virtual ~Singleton_Shared_Ptr();
//---------------------------------------------------------------------
// Public methods
//---------------------------------------------------------------------
public:
//! Returns a pointer to the instance.
static boost::shared_ptr<Target> ptr(void);
//! Returns a reference to the instance.
static Target & ref(void);
//---------------------------------------------------------------------
// Protected methods
//---------------------------------------------------------------------
protected:
//! Default constructor.
Singleton_Shared_Ptr();
//---------------------------------------------------------------------
// Private methods
//---------------------------------------------------------------------
private:
//! Copy constructor, not implemented.
/*! The copy constructor is declared so that the compiler will not
* automatically generate one.
*/
Singleton_Shared_Ptr(const Singleton_Shared_Ptr& s);
//! Assignment operator, declared but not defined.
/*! The assignment operator is declared so that the compiler will not
* automatically generate one.
*/
Singleton_Shared_Ptr& operator=(const Singleton_Shared_Ptr& s);
//---------------------------------------------------------------------
// Private members
//---------------------------------------------------------------------
private:
static wxMutex m_instance_mutex;
};
template<class Target>
wxMutex Singleton_Shared_Ptr<Target>::m_instance_mutex;
//-------------------------------------------------------------------------
// Singleton_Shared_Ptr Constructors & Destructors
//-------------------------------------------------------------------------
template <class Target>
inline
Singleton_Shared_Ptr<Target> ::
Singleton_Shared_Ptr()
{
}
template <class Target>
inline
Singleton_Shared_Ptr<Target> ::
~Singleton_Shared_Ptr()
{
}
//-------------------------------------------------------------------------
// Singleton_Shared_Ptr methods in alphabetical order
//-------------------------------------------------------------------------
template <class Target>
boost::shared_ptr<Target>
Singleton_Shared_Ptr<Target> ::
ptr(void)
{
static boost::shared_ptr<Target> p_instance;
if (p_instance.get() == NULL)
{
wxMutexLocker lock(m_instance_mutex);
if (!p_instance)
{
p_instance.reset(new Target);
}
}
return p_instance;
}
template <class Target>
Target &
Singleton_Shared_Ptr<Target> ::
ref(void)
{
return *(ptr());
}
Вот использование singleton:
class Manager
: public Singleton_Shared_Ptr<Manager>
{
//---------------------------------------------------------------------
// Friends
//---------------------------------------------------------------------
friend class Common::Singleton_Shared_Ptr<Manager>;
//---------------------------------------------------------------------
// Public Constructors and Destructors
//---------------------------------------------------------------------
public:
//! destructor
virtual ~Manager();
//---------------------------------------------------------------------
// Protected Methods
//---------------------------------------------------------------------
protected:
//! Constructor
Manager();
//! Copy constructor -- declared but not implemented.
Manager(const Manager& m);
//! Assignment operator -- declared but not implemented.
Manager& operator= (const Manager& m);
};