C++总结之template

函数模板

咱们能够把函数模板当作一种特殊的函数,里面的参数类型能够是任意类型,这样的话咱们就能够减小重复定义,从而让这个函数模板自动适应不一样的参数类型,也就是说函数能够适应多种类型的参数,例如doubleint或者类什么的。ios

C++为了实现上面的功能,引入了template这个概念。咱们能够把template当成是一种特殊的类型参数,而且也能够在函数里当作参数传递,内心面把它当作int什么的就好了。ide

使用类型参数声明函数模板的格式以下所示:函数

template <class identifier> function_declaration;
template <typename identifier> function_declaration;    // 这里使用了typename 当作声明类型参数

上面声明函数模板的格式只有一处不一样,那就是classtypename,在这里其实使用哪种都没有区别,看本身喜欢就行,C++对此也没有作严格的区分;spa

为了更好的说明如何使用函数模板,便在举一个很形象的例子,那就是一个用来返回较大值的函数,具体写法以下所示:code

template <typename T>
T GetMax(T a, T b)
    return a > b ? a : b;

在上面的短短几行代码中咱们就建立了一个函数模板用来获取两个数之间较大的那个数,不难看出T在这里并无指明具体的类型,在这咱们仍然能够在内心把它当作普通变量处理,返回值也是T。接口

为了使用咱们定义的函数模板,能够参照统一的函数模板调用格式:element

function_name<type> (parameters);    // type就是具体的类型,例如int、double这些,parameters就是函数里的参数,也是具体类型

因此,若是咱们想要实现获取两个整形值里较大的那个,咱们能够传入int这个类型以后调用GetMax函数,具体示例以下:get

int x = 4;
int y = 2;

int max = GetMax<int> (x, y);    // max = 4

类模板

因为template声明的类型能够是任意类型,也就是使用的时候传入具体的类型就行。因此能够参考上面函数模板的例子构造类模板也是同样的,在使用这个类的时候传入具体的变量类型就好了。例以下面的类模板定义:io

template <typename T>
class MyPair{
    T value[2];
    
    public:
        MyPair(T first, T second)
        {
            value[0] = first;
            value[1] = second;
        }
  };

类模板的示例代码中定义一个MyPair类,用来存储任意类型的两个元素,例如doublecharint等,下面我就给出两个示例,分别存储doubleint类型的变量function

MyPair<int> myInt(2, 3);    // 存储两个整型值
MyPair<double> myDouble(2.3, 3.43);    // 存储两个double值

模板类的成员函数也能够在类外定义,写法和函数模板的写法是同样的,具体示例以下所示:

template <class T>
class MyPair {
    T a, b;
  public:
    mypair (T first, T second)
      {a=first; b=second;}
    T Getmax ();
};

template <typename T>
T MyPair<T>::Getmax ()    // 在类外定义函数, 注意前面的写法和函数模板写法一致
{
  T retval;
  retval = a>b? a : b;
  return retval;
}

模板特化

若是咱们想要为类模板定义一个不一样的实现接口,而且要求须要将特定参数做为参数传递时,那么咱们就能够将该模板特化

为了更好地说明模板特化,仍是举个简单的例子吧。假设咱们定义一个类mycontainer,这个类能够存储一个任意类型的变量,而且这个类还有一个函数叫作increasement用来将存储的类型加一。而且,若是这个类存储的是一个char类型的时候,咱们会发现这个类对于实现将其中的成员变量转换为大写的功能将更加方便,不妨将这个函数定义为ToUpper,所以,咱们能够为char类型的类模板实现模板特化,具体的示例代码以下:

// 模板特化
#include <iostream>
using namespace std;

// 声明类模板:
template <typename T>
class mycontainer {
    T element;
  public:
    mycontainer (T arg) {element=arg;}
    T increase () {return ++element;}
};

// char类型的模板特化:
template <>
class mycontainer<char> {
    char element;
  public:
    mycontainer(char arg) {element=arg;}
    
    char ToUpper()
    {
      if ((element>='a')&&(element<='z'))
      element+='A'-'a';
      return element;
    }
};

对于上面的模板特化,咱们须要几点,注意类模板和模板特化的区别和联系

  • 在类模板的前面加上template <>,这代表是模板特化,也就是是说模板特化都须要加上这句话;
  • 还有一点就是类模板后面使用了<char>参数,这个特定参数表示咱们将模板类特化程<char>类型;

template的其余用法

除了以template或者class关键字开头声明的表示类型的模板参数以外,template也能够具备其余类型的参数,例如intdouble这些参数,就相似于一个函数中拥有多个参数,每一个参数类型还不同。为了更好的说明template的其余用法,不妨参考下面的示例代码,

#include <iostream>
using namespace std;

template<class T, int N>    // 这里除了含有class声明的类型以外,还拥有一个int类型
class mysequence {
    T memblock [N];
  public:
    void setmember(int x, T value);
    T getmember(int x);
};

template<class T, int N>
void mysequence<T,N>::setmember(int x, T value) {
  memblock[x]=value;
}

template<class T, int N>
T mysequence<T,N>::getmember(int x) {
  return memblock[x];
}

int main(){
  mysequence<int,5> myints;
  mysequence<double,5> myfloats;
  myints.setmember(0,100);
  myfloats.setmember(3,3.1416);
  cout << myints.getmember(0) << '\n';
  cout << myfloats.getmember(3) << '\n';
  return 0;
}
相关文章
相关标签/搜索