自己实现的Meyers’ Singleton的单例模式模板类。
1 不继承
具体类无需继承, 使用Singleton<Test>::getInstance()获得唯一实例。
template<typename T>
class Singleton
{
private:
Singleton() = default; // 设置为私有(protected也行),禁止外部直接构造
public:
Singleton(const Singleton&) = delete; // 禁止拷贝构造
Singleton& operator = (const Singleton&) = delete; // 禁止拷贝赋值
~Singleton() = default;
public:
static T& getInstance() // Meyers' Singleton
{
static T instance;
return instance;
}
};
class Test
{
public:
Test() = default;
~Test() = default;
public:
void Func() { std::cout << "Test::Func()" << std::endl; }
};
#define TestInstance Singleton<Test>::getInstance() // 这里注意没有分号
调用如下:
int main()
{
TestInstance.Func();
return 0;
}
这种实现方式简单、方便,无需继承。
由于无需继承,通过Test类声明无法知道该类为单例类,意义不明确。
由于Singleton中需要调用Test的构造函数,所以必须将其声明为public。这会导致无法阻止外部直接构造Test对象。
2 继承
template<typename T>
class Singleton
{
public:
~Singleton() = default;
static T& getInstance() // Meyers' Singleton
{
static T instance;
return instance;
}
private:
Singleton(const Singleton&) = delete; // 禁止拷贝构造
Singleton& operator = (const Singleton&) = delete; // 禁止拷贝赋值
protected: // 允许被继承类调用
Singleton() = default; // 设置为私有,禁止外部直接构造
};
class Test : public Singleton<Test>
{
public:
void Func() { std::cout << "Test::Func()" << std::endl; }
public: // 只能为public,否则编译报错,不能阻止外部调用
Test() = default;
};
#define TestInstance Test::getInstance()
Test继承Singleton,通过类声明就知道Test是个单例类。但是构造函数依然只能声明为public,导致外部依旧能直接调用构造Test对象。
3 继承+友元
template<typename T>
class Singleton
{
public:
friend typename T; // 友元声明
public:
~Singleton() = default;
static T& getInstance() // Meyers' Singleton
{
static T instance;
return instance;
}
private:
Singleton(const Singleton&) = delete; // 禁止拷贝构造
Singleton& operator = (const Singleton&) = delete; // 禁止拷贝赋值
private:
Singleton() = default; // 设置为私有,禁止外部直接构造
};
class Test : public Singleton<Test>
{
public:
friend class Singleton<Test>; // 友元声明
public:
void Func() { std::cout << "Test::Func()" << std::endl; }
private: // 构造函数可以声明为private,阻止外部直接调用
Test() = default;
};
#define TestInstance Test::getInstance()
通过相互声明为友元,Test的构造函数即使声明为private,Singleton的依旧能访问其构造函数,不会编译报错。
同时private阻止外部直接构造Test对象,只能通过Test::getInstance()获取唯一实例。当然,这就要求新类继承自Singleton时必须将Singleton声明自己的友元类。
4 继承+友元(小改版)
template<typename T>
class Singleton
{
protected: // 不能直接构造,同时子类可访问,这是protected的优势
Singleton() = default;
public: // 不提供拷贝构造函数和赋值函数
Singleton(const Singleton& one) = delete;
Singleton& operator=(const Singleton& one) = delete;
public: // 全局访问函数
static T& GetInstance()
{
static T instance;
return instance;
}
};
class Test : public Singleton<Test> // 继承自Singleton<TestClass>
{
public: // 必须提供
friend Singleton<Test>;
private: // 不能直接构造,也可使用protected
Test() = default;
public:
void TestFunc()
{
}
};
当Test继承子Singleton<Test>后,需要改动的地方有两处:
- 声明Singleton<Test>为友元。
- 声明构造函数为private或者protected。
感觉还是比较麻烦,想最终实现的功能是:一个类想要变成单例类,只需要继承自单例模板类即可,无需再做其他修改。