浅析C++模板
发布于 2021-01-20 17:28
模板概述:
函数模板:
函数模板的定义:
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为int
cout << 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)文件,但是,模板则不同,为了生成一个模板实例,编译器需要掌握函数模板或类模板成员函数的定义。
因此,模板的头文件通常即包括声明,也包括定义。这是因为当非模板时,编译器只需要掌握声明即可,而模板时编译器既要掌握声明也要掌握定义。
类模板:
与函数模板不同,编译器不能为类模板推断参数类型,因此我们必须在类模板的尖括号中提供额外的信息,用来代替模板参数的模板实参列表。
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 我们将第一时间删除。
相关素材