类模板的派生和模板类的派生

//下面是我自己总结理解的,还在查找依据当中。

1. 类模板 vs  模板类 

   类模板是模板的一种, 可以在使用时确定类的类型。

 类模板不是一个类,不能直接用于生成对象。  Foo f;是错误的。

template< class T>
class Foo
{
    T tVar;
   //...
};

  模板类 就是 类模板的一个实例,是一个确定了类型的 具体的类。可以直接生成对象。

   Foo<int>   或  Foo<double>  就是两个Foo的模板类。 可以直接生成对象 Foo<int> fi;   Foo<double>  fd;  都正确。

2.模板类的派生。  此处模板类也称为“非依赖型基类”

模板类就是一个具体的类,和一般的类没有区别,派生时也没有区别。

class Sun : public Foo<int>
{
  //tVal是int    
}

class Sun2: public Foo<double>
{
 //tVal是double
} 

  但,当派生类是一个类模板的时候,有一个问题需要注意。在派生类中的非限定类型的查找,会先查找这个非依赖型基类,然后才会查找模板参数列表。

template<typename T>
class Base
{
public:
	int basefield;
	typedef int T;
};

template<typename T>
class D2:public Base<double>
{
public:
	void f() { basefield = 7; }//正常访问继承成员
	T strange;   //T是Base<double>::T,而不是模板参数 。
};

  3.类模板的派生。 --派生类也一定是模板

  这种情况下,应注意的问题是:非依赖性名称(即普通成员,跟T类型没关系的)不会在依赖基类中查找  (注,Windows的VC已经让这种方式通过编译了。)

template<typename T>
class Base
{
public:
	int basefield;
};

template<typename T>
class D2:public Base<T>
{
public:
	void f() { basefield = 7; }//不认识basefield
	
};

  解决方法就是将非受限名称改为受限名称。  简单来说就是显示的说明basefield是这个类的成员。

   1)this->basefield = 7;

   2) Base<T>::basefield =7;

      但用这种方式的问题是,如果该成员是个虚函数,则失去了多态的性质。

  

至于为什么明明是父类的成员 却 在子类中被隐藏了,是因为模板存在特化。特化相当于是另一个类,所以很可能在特化版本中,根本没有这个成员。

为了防止在继承特化版本,调用该成员时报错,就假定不知道 父类中有没有这个成员,所以需要显式说明。  具体可以参看<<Effective C++>>条款43.

路是一步一步走的
原文地址:https://www.cnblogs.com/Lalafengchui/p/4613427.html