自身特化的模板类:奇异循环模板

      考虑如下代码:

template
class CBase
{
public:
	CBase();
	~CBase();

	static	int*	m_pValue;
};

class  CDriver	  :  public CBase
{
public:
	int	m_key;
}

      上面的代码出现了2个问题:

1.   模板类的T,在整个模板类中并没有用到

2.   派生类以特化的模板类作基类,但是却用自身特化

实际上,这两个问题是为了实现同一个功能:

CBase是个模板类,但其有个static成员函数指针。那么:

class CDriverA    : public CBase<int>

class CDriverB    : public CBase<int>

      如果是这样的代码,CDriverACDriverB会从同一个特化模板派生,则CDriverACDriverB会共享这个static成员函数指针。若不希望共享,可以采用这样的方式:

class CDriverA    : public CBase<int>

class CDriverB    : public CBase<double>

      这样,CDriverACDriverB会从不同特化模板派生,从而CDriverACDriverB不共享这个static成员函数指针。

      而实际上,由于T类型并没有在模板中使用,因此编译时这个T是什么并不重要。

于是:

class CDriverA    : public CBase<CDriverA>

class CDriverB    : public CBase<CDriverB>

      这样的代码是合法的,并且其特化模板不同,从而CDriverACDriverB不共享这个static成员函数指针。

      这就是用template实现多态的方法。

 

      实际上,在模板类中,只要不涉及T的“实际实现”,即便代码中有T也是可以的。

      不涉及实际实现的情况有以下几个:

1.   T作函数返回值,包括T&与T*

2.   T作函数成员变量,一定要是T*

 

示例代码:定义一个单件父类,从而派生类都是单件:

templateclassSingleton
{
protected:
	Singleton(){};
	Singleton(constSingleton&){};
Singleton&operator=(constSingleton&){};
	~Singleton();
public:

	staticT&GetInstance();

	staticT*GetInstancePtr();

private:
	staticT*	_instance;
};

template
T*Singleton::_instance=nullptr;

template
Singleton::~Singleton()
{
	if(_instance!=nullptr)
	{
		delete	_instance;
		_instance	=	nullptr;
	}
}

template
T&Singleton::GetInstance()
{
	if(_instance==nullptr)
	{
		_instance=newT;
	}

	return*_instance;
}

template
T*Singleton::GetInstancePtr()
{
	if(_instance==nullptr)
	{
		_instance=newT;
	}

	return_instance;
}

在派生类中:

#include"Singleton.h"

class MyClass : public Singleton
{
	public:
		intgetNumber() { return 1199;  }
	private:
		MyClass() {};
		//MyClass(constMyClass&) {};
		//MyClass& operator =(constMyClass&) {};
		~MyClass() {};

		 friend Singleton;
		//friend class auto_ptr;
}

上述代码就是一个奇异循环模板及其派生类。

      注意:

1.   模板类的构造函数,拷贝构造函数,=运算符和析构函数不可以为private,因为private函数不能被派生类访问。考虑到是单件,定义为public并不合适,故定义为protected最合适。

2.   派生类中,由于是循环模板,所以相当于是令基类访问自身,所以要添加:

friend Singleton;

这样,基类就可以访问自身。

3.   派生类无法再派生。

4.   实际上,派生类的构造函数,拷贝构造函数,=运算符和析构函数都可以不再定义。

  

      注意上面的代码仅适用于单线程。若要在多线程下使用,需要在getInstance()函数中引入加锁和双检测机制。

你可能感兴趣的:(C++)