C++ 单例模式 模版类(Meyers' Singleton)

自己实现的Meyers’ Singleton的单例模式模板类。

实现1(不继承)

具体类无需继承, 使用Singleton::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::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声明自己的友元类。

你可能感兴趣的:(C++,For,Interview,Design,Pattern)