c++ - 是否可以强制仅通过单例实例化一个类
问题描述
当我使用 C++11 进行编码时,我通常使用设计模式 Singleton。这是我设计单身人士的方式:
template<typename T>
class Singleton {
private:
Singleton() = default;
~Singleton() = default;
public:
static T * GetInstance() {
static T t;
return &t;
}
Singleton(const Singleton &) = delete;
Singleton(Singleton &&) = delete;
Singleton & operator=(const Singleton &) = delete;
Singleton & operator=(Singleton &&) = delete;
};
然后,我们可以定义我们想要的任何类,例如class Test{};
,Singleton<Test>::GetInstance();
并将生成一个对象。
一切正常。
但是,今天我认为这class Test{};
可以摆脱限制。我的意思是,即使我定义了 class Singletion<T>
,但其他开发人员可以定义他们的类,例如Test
,并且不要使用Singleton
,因此他们可以根据需要生成许多对象。但我想要的是,如果你决定定义一个应该是单例的类,你不能通过调用构造函数来生成对象,而只能通过调用Singleton<Test>::GetInstance()
.
总之,我想得到这个:
Test t; // compile error
Test *p = Singleton<Test>::GetInstance(); // OK
为此,我尝试了一些棘手的方法,例如,我让类Test
继承Singleton<Test>
:
class Test : public Singleton<Test> {
public:
Test() : Singleton<Test>() {}
};
因此,如果您正在定义一个应该是单例的类,则继承该类Singleton
,现在您的类无法通过调用构造函数生成任何其他对象。但它不起作用,因为它的构造函数Singleton
是私有的。但是如果我friend T;
在课堂上写Singleton
,Test t;
就会变得合法......
看来我不能强制类用户仅通过 Singleton 来构造对象。
有人能帮我吗?或者告诉我我正在做一些不可能的事情......
解决方案
您可以使用 CRTP 模式来实现这一点
template <class T>
class Singleton {
public:
Singleton& operator = (const Singleton&) = delete;
Singleton& operator = (Singleton&&) = delete;
static T& get_instance() {
if(!instance)
instance = new T_Instance;
return *instance;
}
protected:
Singleton() {}
private:
struct T_Instance : public T {
T_Instance() : T() {}
};
static inline T* instance = nullptr;
};
class Example : public Singleton<Example> {
protected:
Example() {}
};
int main()
{
auto& test = Example::get_instance();
Example e; // this will give you error
}
推荐阅读
- appium - Appium 的 driver.reset() 和“noReset”或“fullReset”功能之间有什么关系吗?
- dataframe - 在 Spark 中重新分区更改数据帧的行顺序
- python - sqlite3.OperationalError:输入不完整
- git - 使用 Github API 保护 Github 分支
- javascript - 使用 Javascript 打开私有/隐身窗口
- c# - 如何在 PowerShell 中覆盖 Collection 对象的“成员枚举”行为
- java - 如果调用的进程正在运行,Java Swing ComponentResized 不会触发
- sql-server - DATALENGTH 不计算 SQL Server 中的无换行符 (0xA0) 字符
- java - Java流合并和输出
- logging - 如何停止 Rails.autoloaders.logger?