从唯一实例谈静态成员

在实际的项目中我们可能需要这样一种类,它的对象在整个项目中只能有一个,在整个程序中只能创建一个类的对象,比如说,最常用的mp3播放软件Winamp,由于它需要独占计算机中的音频设备,因此该程序只允许自身运行唯一的一个例程。

c++并没有提供这一特性,我们可以自己封装一个唯一实例的类,为了完成这个工作,我们需要一个静态的整型数据成员用于记录当前程序中类的实例个数,还需要一个指向自身的静态指针,指向新创建的类的对象。实现的代码如下:

class CSingle  
{
private:
	CSingle(){};
	CSingle(CSingle &r){};
<span style="white-space:pre">	</span>void operator = (CSingle &r){}; 
	~CSingle(){};

public:
	static CSingle* Create();
	static void Release();

private:
	static int m_nCount;
	static CSingle *m_pInstance;
};
int CSingle::m_nCount = 0;
CSingle *CSingle::m_pInstance = NULL;

CSingle* CSingle::Create()
{
	if (0 == m_nCount)
	{
		m_nCount++;
		m_pInstance = new CSingle;
	}else
	{
		return NULL;
	}

	return m_pInstance;
}

void CSingle::Release()
{
	if (0 != m_nCount)
	{
		delete m_pInstance;
		m_nCount--;
	}

	return;
}
利用一下代码测试:

	CSingle *pObj = CSingle::Create();

	CSingle *pObj1 = CSingle::Create();

	cout<<pObj<<endl;
	cout<<pObj1<<endl;

	CSingle::Release();

上述代码使用的是类的静态成员,静态成员用static关键字进行说明,类的静态成员可以是静态数据成员,也可以是静态函数成员,下面分别来说明这两个内容:

类的成员函数:我们知道一般程序用来存储变量的内存分为静态存储区,和堆栈段,静态存储区用于存储静态变量和全局变量,而堆栈段用来存储函数中定义的局部变量,也就是说静态变量和全局变量在同一段内存空间中,也可以相当于一个全局变量,关键字static除了在定义静态变量的时候使用外,还可以作为限定符,限定定义的变量只能在某一区域内可见,在函数中定义的只在该函数中可见,在文件中定义的只在该文件中可见。所以说静态变量是一种限定了可见区域的全局变量,在类中定义的静态数据变量被限定只在类中可见,与类的普通成员间最大的区别在于普通成员只有在类存在时才会在内存中真正存在,而静态成员一旦定义就已经存在,且在整个内存中只有一份,这也就是说所有类共享这一个静态变量,任何一个类修改了变量的值,都会影响到其他类。因为它们有类的生命周期无关,所以不论类是否创建了对象,都可以使用它们,只是需要加上类域,因为static已经限定了它们只在类中可见。

类的成员函数:静态函数成员与静态数据成员类似,也是相当于一个全局函数,所有类公用一份,它与类函数的不同在于,普通的类函数都会由编译器隐式的传入一个this 指针,而静态成员没有传入这样一个值,也就意味着这个函数并不知道是哪个类的对象在调用它,自然也就不知道该如何使用哪个类对象的普通成员,所以说c++规定静态函数成员不能访问非静态数据成员,而静态数据成员,所有类共享,所以只能访问静态数据成员。静态函数成员也受类的保护限制,即不能通过对象打点调用对象的私有成员。

接下来分析这个程序,首先唯一实例必须用静态数据成员计算当前有几个类的实例,不能用普通的内成员,否则每个类都有一个计数器,而每个类的计数器可能都为1,这样达不到唯一的效果。如果用构造函数初始化的话,每个类对象都共享这块内存,所以我们如果用构造函数初始化,每个类的构造函数都有可能会修改这个值,导致错误的结果,所以我们不用类的构造函数,只能将它私有化,不让系统调用构造函数,系统提供了3中默认的构造函数,分别是不带参的构造函数、拷贝构造函数、赋值运算符重载的构造函数,所以为了不让系统调用任何默认构造,我们将这3个构造函数私有化,并且在构造函数中不做任何事情。不能用构造函数创建对象,也就是说我们需要利用其它方法创建对象,既然没有构造函数,那么通过对象打点调用其它函数创建肯定也是不可能的,我们需要一种函数即使类对象没有它们也存在,静态函数成员正是这种函数,所以我们需要创建的静态函数成员,并且通过动态内存创建一个类的对象,并用静态数据成员保存该指针。至此我们已经完成了一个唯一实例的类。




原文地址:https://www.cnblogs.com/lanuage/p/7725767.html