浅析C++模板

发布于 2021-01-20 17:28

模板概述:

模板是C++泛型编程的基础,模板就像一个模型,你给不同的参数,它都按照相同逻辑去定义和执行。

 

函数模板:

函数模板的定义:

当函数的功能一样,或者类似,这个时候我们就可以定义一个函数模板,而不是为每个类型都定义一个新函数。例如比大小函数,我们可以这样定义:

 

template<typename T>int compare(const T &v1, const T &v2){if (v1 < v2) return -1;if (v2 < v1) return 1;return 0;}

函数模板的定义以关键字template开始,后跟一个模板参数列表。

 

函数模板的调用

cout << compare(1, 0) <<endl;        //        T为intcout << compare(1.5,5.1) <<endl;        //        T为double

相当于将上面的模板参数T分别用int和double代替。需要注意的是类型定义时必须加上关键字class或者typename,且二者可以没有区别,一般现在大家习惯使用typename。

 

template<typenameT1, class T2 > fun1(const T1&, constT2&);        //正确template<classT1, typename T2 > fun1(const T1&, constT2&);        //正确template<typenameT1, typename T2 > fun1(const T1&, constT2&);        //正确template<typenameT1,  T2 > fun1(const T1&, constT2&);        //错误,T2未定义


模板编译

当编译器遇到一个模板定义时,他并不生成代码,只有当我们实例化(调用)模板时,编译器才会生成代码。通常来说,我们习惯将函数和类的定义放在声明文件中(.h),将函数和类的实现放在源文件中(.cpp)文件,但是,模板则不同,为了生成一个模板实例,编译器需要掌握函数模板或类模板成员函数的定义。

因此,模板的头文件通常即包括声明,也包括定义。这是因为当非模板时,编译器只需要掌握声明即可,而模板时编译器既要掌握声明也要掌握定义。

 

类模板:

与函数模板不同,编译器不能为类模板推断参数类型,因此我们必须在类模板的尖括号中提供额外的信息,用来代替模板参数的模板实参列表。

 

#include<iostream>#include<string>using namespace std;template<class T1, class T2>class Pair{public:T1 key;  //关键字T2 value; //值Pair(T1 k, T2 v) :key(k), value(v) { };bool operator < (const Pair<T1,T2> & p) const;}; template<classT1,class T2>boolPair<T1,T2>::operator < (const Pair<T1,T2> & p) const{return key < p.key;} int main(){Pair<string, int> student("Tom",19); //实例化出一个类 Pair<string,int>cout << student.key << " " <<student.value;return 0;} 程序的输出结果是:Tom 19

类模板的实例化必须给出额外的信息:

Pair<string,int> student("Tom", 19);//实例化出一个类 Pair<string,int>。

当我们在类外定义一个成员时,必须说明成员是哪个类,这是因为我们在模板外定义其成员时,我们并不在类的作用域中,直到遇到类名才会进入类的作用域,而模板是其类名的一部分,其定义格式参考示例程序。

 

成员模板

一个类(无论是普通类还是类模板)可以包含本身是模板的成员函数。这种成员被称为成员模板。成员模板不能是虚函数。

这里父类对象不能直接向下转型,但子类对象可以调用父类构造函数。引用侯捷大师的一个例子就很说明问题了。

 

template<class T1,class T2>structpair  {  typedef T1 first_type;  typedef T2 second_type;  T1 first;  T2 second;  pair() :first(T1()),second(T2())  { }  pair(const T1& a,const T2& b):first(a), second(b)  {  }   template <class U1,class U2>  //这里,模板套模板,成员模板  pair(const pair<U1,U2>& p)    : first(p.first),second(p.second)  {  }};  class Base1{};//鱼类class Derived1:public Base1{};//鲫鱼class Base2{};//鸟类class Derived1:public Base2{};//麻雀  pair<Derived1,Derived2> p;//鲫鱼和麻雀pair<Base1,Base2> p2(p);//用鲫鱼和麻雀初始化鱼类和鸟类,相当于(1)//(1)//pair<Base1,Base2>p2(pair<Derived1,Derived2>());  //用子类初始化父类

 

后语:泛型编程是C++的精华所在,有兴趣进一步讨论的同学建议看一下侯捷大师的书:

    深度探索C++对象模式

    C++ STL与泛型编程

本文来自网络或网友投稿,如有侵犯您的权益,请发邮件至:aisoutu@outlook.com 我们将第一时间删除。

相关素材