您的位置:首页 > 其它

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

2018-02-02 08:40 169 查看
      考虑如下代码:

template<typename T >
class CBase
{
public:
CBase();
~CBase();

static	int*	m_pValue;
};

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


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

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

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

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

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

class CDriverA    : public CBase<int>

class CDriverB    : public CBase<int>

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

class CDriverA    : public CBase<int>

class CDriverB    : public CBase<double>

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

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

于是:

class CDriverA    : public CBase<CDriverA>

class CDriverB    : public CBase<CDriverB>

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

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

 

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

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

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

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

 

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

template<typenameT>classSingleton
{
protected:
Singleton(){};
Singleton(constSingleton&){};
Singleton&operator=(constSingleton&){};
~Singleton();
public:

staticT&GetInstance();

staticT*GetInstancePtr();

private:
staticT*	_instance;
};

template<typenameT>
T*Singleton<T>::_instance=nullptr;

template<typenameT>
Singleton<T>::~Singleton()
{
if(_instance!=nullptr)
{
delete	_instance;
_instance	=	nullptr;
}
}

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

return*_instance;
}

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

return_instance;
}


在派生类中:

#include"Singleton.h"

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

friend Singleton<MyClass>;
//friend class auto_ptr<MyClass>;
}


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

      注意:

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

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

friend Singleton<MyClass>;

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

3.   派生类无法再派生。

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

  

      注意上面的代码仅适用于单线程。若要在多线程下使用,需要在getInstance()函数中引入加锁和双检测机制。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: