首页 > 代码库 > c++ 单例模式 对全局变量的替代
c++ 单例模式 对全局变量的替代
前段时间要实习一个充值接口,创建了一个类(就叫类A好了),这个类A要和另外3个类进行交互,3个类对类A修改的数据是对其他类可见的。这种情况我想到了3个方法:
1.static 静态成员,静态成员为该类的所有实例所共享,3个类中各自创建一个类A的对象,它们对静态成员的修改对其他类可见。
2.全局变量,类A的头文件中添加 extern classA g_classA; 源文件中添加 classA g_classA; 3个类中添加头文件后直接通过g_classA //这种不推荐
3.单例模式
使用单例模式替代全局变量,3个类对类A的函数访问都是对类A的唯一实例的数据访问,修改对其他类自然可见了。单例模式是使用全局变量的常见替代方法。
下面是转自一位前辈的单例实现模式的总结,第三种实现实在太精彩了,只能用"nice catch"来形容!
——————————华丽的分割线——————————
转自:http://lwzy-crack.blog.163.com/blog/static/9527204220091068526135/
C++中的单例模式
单例模式很有用,使用单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
但是在程序的开发过程中我们总是遇到一些问题,而这些问题主要集中在单例类的消毁过程中,普通使用的单例模式的类如下:
class Singleton:
{
// 其它成员
public:
static Singleton * GetInstance()
{
if (m_pInstance == NULL)
m_pInstance = new Singleton();
return m_pInstance;
}
private:
Singleton(){};
static Singleton * m_pInstance;
}
可是这个类在什么时候调用它的析构函数呢,我们怎么消毁它。提供一个公用的destroy函数来进行它的消毁吗,这很不美观。最后我就在网上找到了如果下的代码处理了这个问题:
class Singleton:
{
// 其它成员
public:
static Singleton * GetInstance(){...}
private:
Singleton(){};
static Singleton * m_pInstance;
class CGarbo // 它的唯一工作就是在析构函数中删除Singleton的实例
{
public:
~CGarbo(){
if (Singleton::m_pInstance)
delete Singleton::m_pInstance;
}
};
static CGarbo Garbo; // 定义一个静态成员,在程序结束时,系统会调用它的析构函数
}
这是非常好的方法,静态成员对象 Garbo 在析构时会自动的消毁单例,我们不用再担心这个问题了。
但是添加一个类的静态对象,总是让人不太满意,所以有人用如下方法来重现实现单例和解决它相应的问题,代码如下:
class Singleton:
{
// 其它成员
public:
static Singleton &GetInstance(){
static Singleton instance;
return instance;
}
private:
Singleton(){};
}
使用局部静态变量,非常强大的方法,完全实现了单例的特性,而且代码量更少,也不用担心单例消毁的问题。
在后期的项目中我全使用了这种方法,可是在项目的开发过程中还是出现了问题,当如下方法使用单例时问题来了,
Singleton singletion = Singleto::GetInstance();
这么做就产生了一个类拷贝的问题,这就为背了单例的特性。
产生这个问题的原因在于,编译器会为类生成一个默认的构造函数,来支持类的拷贝。
最后没有办法,我们要禁止类拷贝和类赋值,禁止程序员用这种方式来使用单例,当时领导的意思是GetInstance()函数返回一个指针而不是返回一个引用,函数代码改为如下:
static Singleton *GetInstance(){
static Singleton instance;
return &instance;
}
可我总是感觉不好,为什么不让编译器不这么干呢。这时我才想起可以显式的声明类拷贝的构造函数,和重载=操作符,新的单例类如下:
class Singleton:
{
// 其它成员
public:
static Singleton &GetInstance(){
static Singleton instance;
return instance;
}
private:
Singleton(){};
Singleton(const Singleton&);
Singleton & operate = (const Singleton&);
}
关于Singleton(const Singleton&);和Singleton & operate = (const Singleton&);函数,我们要声明成私用的,并且只声明不实现。这样子后如果用上面的方式来使用单例时,不管是在友元类中还是其它的,编译器都是报错。
不知道这样的单例类是否还会有问题,但在程序中这样子使用已经基本没有问题了。
——————————华丽的分割线——————————