C++ 单例模式怎么写

之前也用单例,虽然没出现过什么问题,但是我之前的写法还是存在一些问题的。所以就记录一下C++ 单例的心路历程:

之前的不太正确的写法

//ApplicationService.h
    class ApplicationService
	{
		ApplicationService();
	public:
		static ApplicationService * Instance();
		~ApplicationService();
	public:
	...
	};
	
//ApplicationService.cpp
	ApplicationService::ApplicationService() {}

	ApplicationService * ApplicationService::Instance()
	{
		static ApplicationService app;
		return &app;
	}

	ApplicationService::~ApplicationService() {}

总的思想就是构造私有化,外部的变量无法访问构造函数就没法创建实例了。
使用即用 ApplicationService::Instance() 就可以了。但是很多时候有可能出现使用其他默认构造函数的调用,这样就会导致一些问题。
前段时间看SOUI 和Duilib 的源代码时候看到他们的单例是怎么写之后我感觉自己的单例类写的很是危险,所以及时更正了,但是这个单例模式的代码千篇一律,总是写重复的代码也是很烦。就参考了Duilib 中的宏定义。

#ifndef SINGLETON_H
#define SINGLETON_H

namespace core
{

#define SINGLETON_DEFINE(TypeName)				\
static TypeName* GetInstance()					\
{												\
	static TypeName type_instance;				\
	return &type_instance;						\
}												\
												\
TypeName(const TypeName&) = delete;				\
TypeName& operator=(const TypeName&) = delete

}

#endif //! SINGLETON_H

很多人说这样的代码风格出了问题会很难排查错误,但是这样写单例就可以复用代码了。
这里的宏定义没有写构造函数,因为很多情况下构造函数需要处理一些参数,所以构造函数不适合写到宏定义内。最终代码如下:

#include "common.h"

namespace core
{
	using namespace std;
	class ApplicationService
	{
		ApplicationService();
	public:
		SINGLETON_DEFINE(ApplicationService);
		~ApplicationService();
	public:
	...
	};
}

设计思想就是删除编译器默认生成的特殊成员函数。
这里引用一下 https://zh.cppreference.com 的说明:
cppreference - C++/C++ 语言/类
从Cppreference 上的说明可以看出来,编译器会定义一些特殊的成员函数。所以为了特别的调用方式出发新实例的产生,就需要显示的将这些函数删掉,值得注意的事C++11起 多了移动构造函数和移动赋值运算符,所以我又把这两个函数给删除了。见最终的程序代码:

#ifndef SINGLETON_H
#define SINGLETON_H

namespace core
{

#define SINGLETON_DEFINE(class_name)				\
static class_name* GetInstance()					\
{												\
	static class_name instance;				\
	return &instance;						\
}												\
												\
class_name(const class_name&) = delete;				\
class_name& operator=(const class_name&) = delete;	\
class_name(class_name&&) = delete;					\
class_name& operator=(class_name&&) = delete;

//ps:之前 错误的代码,竟然给右值加了 const。。。。
//还好及时有大神指出,万分感谢,错误实例如下
//class_name(const class_name&&) = delete;			
//class_name& operator=(const class_name&&) = delete;
}

#endif //! SINGLETON_H

好了END!!!!


2019年5月15日,昨天写单利时候偷懒直接赋值CSDN代码过去发现有错误,我就检查了一下,发现宏定义最后一行多了一个分号,这样就导致我代码里面不可以加分号,强迫症来了,就来把博客更新一下。注:为了代码风格统一宏定义最后一行一定要少一个分号。
2020年4月17日,又一次回来改,因为大家都宏定义后面都是没有分号的,与主流coding style 一直,我又在宏内加了分号。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值