C++泛型编程:template模板

 

泛型编程就是以独立于任何特定类型的方式编写代码,而模板是C++泛型编程的基础.编程

所谓template,是针对“一个或多个还没有明确的类型”所编写的函数或类.函数

使用template时,能够显示的或隐示的将类型看成参数来传递.ui

下面是一个典型的例子,传回两数中的较大者:this

template<class T>
inline const T& MAX(const T& a,const T& b)
{
   return a>b?a:b;
}

在这里,第一行将T定义为任意数据类型,于函数被调用时由调用者指定.spa

这个类型有关键字class引导,也可用typename引导,typename其实比class更直观.指针

(须要注意的是,若是用到了嵌套依赖类型,则必需要用到typename).code

理解:对象

  第一行template<class T>告诉编译器:我在这儿定义了一个可变类型T,调用者使用什么类型你就怎么编译吧!blog

缺省模板参数get

template class能够有缺省参数,例如一下声明,容许你使用一个或多个template来声明MyClass对象:

template<class T,class container=vector<T> >
class MyClass
{
public:
     MyClass(){}
     ~MyClass(){}
protected:
private:
};

若是只传递一个参数,那么缺省参数可做为第二参数使用:

MyClass<int> x1; // equivalent to:
MyClass<int,vector<int> > x2;

注意:template缺省参数根据前一个(或前一些)参数而定义。这也就意味着若是参数传递列表中某个参数是缺省参数,那么后面的全部参数都应该是缺省参数.

关键字typename

关键字typename被用来作为类型以前的标识符号。考虑下面例子:

template<class SubType>
struct BaseType
{
     SubType a;
};

template <class T>
class MyClass1
{
     typename T::SubType *ptr;
     // ...
};

这里,typename指出SubType是class T中定义的一个类型,所以ptr是一个指向T::SubType的指针.

若是没有typename,SubType将会被当成一个static成员,因而:

T::SubType * ptr;

会被解释为类型T中的两个子成员SubType和ptr的乘积.

成员模板

class成员函数能够是个template,可是这样的成员template类型既不能是virtual,也不能有缺省参数,例如:

class MyClass
{
     //...
     template<class T>
     void f(T);
};

在这里,MyClass::f声明了一个成员函数,适用于任何类型参数.

这个特性经常使用来为template class中的成员提供自动类型转换,例以下面的例子中,assign()的参数x,其类型必须和调用端所提供的对象的类型彻底吻合:

template<class T>
class MyClass
{
public:
     MyClass();
     ~MyClass();
     void assign(const MyClass<T>& x) // x must have same type as *this
     {
           value=x.value;
     }
     // ...
protected:
private:
     T value;
};

若是使用了两个类型,即便两个类型之间能够自动转换,也会出错:

void fun()
{
     MyClass<double> d;
     MyClass<int> i;

     d.assign(d); // OK
     d.assign(i); // ERROR: i is MyClass<int> but MyClass<double> is required
}

理解:

  对于一个template class中的template成员,遵循“先入为主”,若是第一次指定了类型,那么后面都要和第一次保持一致.

但若是要指定两个不一样类型的类成员变量怎么办呢?

方法很简单,咱们将成员变量在使用一个和class不一样的template类型就行:

template<class T>
class MyClass
{
public:
     MyClass();
     ~MyClass();
     template<class X> // member template
     void assign(const MyClass<X>& x) // allow different template types
     {
           value = x.getValu();
     }
     T getValue() const
     {
           return value;
     }
     // ...
protected:
private:
     T value;
};

void fun()
{
     MyClass<double> d;
     MyClass<int> i;
     
     d.assign(d); // OK
     i.assign(i); // OK (int is assigned to double)
}
相关文章
相关标签/搜索