【导读】《21天学通C++》这本书通过大量精小短悍的程序详细而全面的阐述了C++的基本概念和技术,包括管理输入/输出、循环和数组、面向对象编程、模板、使用标准模板库以及创建C++应用程序等。这些内容被组织成结构合理、联系紧密的章节,每章都可在1小时内阅读完毕,都提供了示例程序清单,并辅以示例输出和代码分析,以阐述该章介绍的主题。本文是系列笔记的第八篇,欢迎各位阅读指正!
模板简介
模板声明以关键字template打头,接下来是类型参数列表。这种声明的格式template <parameter list>
示例代码如下:
usingnamespacestd; template<typenameType>constType&GetMax(constType&value1, constType&value2) { if (value1>value2) returnvalue1; elsereturnvalue2; } template<typenameType>voidDisplaycomparison(constType&value1, constType&value2) { cout<<"GetMax("<<value1<<","<<value2<<")="; cout<<GetMax(value1, value2) <<endl; } intmain() { inta1=-101, inta2=2011; Displaycomparison(a1, a2); doubled1=3.14, doubled2=3.1415926; Displaycomparison(d1, d2); stringName1("Jack"), Name2("john"); Displaycomparison(Name1, Name2); return0; }
模板函数不仅可以重用(就像宏函数一样),而且更容易编写和维护,还是类型安全的。请注意,调用Displaycomparison时,也可显式地指定类型,如下所示:
Displaycomparison<int>(Int1,Int2)
;
然而,调用模板函数时没有必要这样做。您无需指定模板参数的类型,因为编译器能够自动推断出类型;但使用模板类时,需要这样做。
模板类
模板类是模板化的 C++类,是蓝图的蓝图。使用模板类时,可指定要为哪种类型具体化类。这让您能够创建不同的Human对象,即有的年龄存储在 long long成员中,有的存储在 int成员中,还有的存储在short成员中。对于模板,术语实例化的含义稍有不同。用于类时,实例化通常指的是根据类创建对象。但用于模板时,实例化指的是根据模板声明以及一个或多个参数创建特定的类型。对于下面的模板声明:
template<typenameT>classTemplateClass{ Tm_member; };
使用模板是将这样编写代码
TemplateClass<int>IntTemplate;
这种实例化创建的特定类型称为具体化。
声明包含多个参数的模板
如下面代码所示:
template<typenameT1, typenameT2>classHoldsPair{ private: T1Value1; T2Value2; public: HoldsPair(constT1&value1,constT2&value2) { Value1=value1; Value2=value2; } //other function declarations};
实例化如下:
HoldsPair<int,double>pairIntDouble(6,1.99); HoldsPair<int,int>pairIntDouble(6,500);
包含默认参数的模板
template<typenameT1=int,typenameT2=int>classHoldsPair{ //……method declare};
实例化可简写为:
HoldsPair<>PairIntDouble(6,500);
实例代码如下:
usingnamespacestd; template<typenameT1=int,typenameT2=double>classHoldsPair{ private: T1Value1; T2Value2; public: HoldsPair(constT1&value1, constT2&value2) { Value1=value1; Value2=value2; }; constT1&GetFirstvalue() const { returnValue1; }; constT2&GetSecondvalue() const { returnValue2; }; }; intmain() { HoldsPair<>mIntFloatPair(300, 10.09); HoldsPair<short,constchar*>mshortstringPair(25, "learn template,love c++"); cout<<"the first object conntains-"<<endl; cout<<"Value 1:"<<mIntFloatPair.GetFirstvalue() <<endl; cout<<"Value 2:"<<mIntFloatPair.GetSecondvalue() <<endl; cout<<"the second object contains-:"<<endl; cout<<"Value 1:"<<mshortstringPair.GetFirstvalue() <<endl; cout<<"Value 2:"<<mshortstringPair.GetSecondvalue() <<endl; return0; }
输出为:
thefirstobjectconntains-Value1:300Value2:10.09thesecondobjectcontains-: Value1:25Value2:learntemplate,lovec++
模板类和静态成员
实例代码如下:
usingnamespacestd; template<typenameT>classTestStatic{ public: staticintStaticValue; }; template<typenameT>intTestStatic<T>::StaticValue; intmain() { TestStatic<int>Int_Year; cout<<"setting staticvalue for Int_Year to 2011"<<endl; Int_Year.StaticValue=2011; TestStatic<int>Int_2; TestStatic<double>Double_1; TestStatic<double>Double_2; cout<<"setting staticvalue for Double_2 to 1011"<<endl; Double_2.StaticValue=1011; cout<<"Int_2.StaticValue= "<<Int_2.StaticValue<<endl; cout<<"Double_1.StaticValue= "<<Double_1.StaticValue<<endl; return0; }
输出为:
settingstaticvalueforInt_Yearto2011settingstaticvalueforDouble_2to1011Int_2.StaticValue=2011Double_1.StaticValue=1011
上述有一条程序初始化模板类的静态成员:template<typename T> int TestStatic<T>::StaticValue
*对于模板类的静态成员,通用的初始化语法如下:
template<typenameparameters>staticTypeClassName<TemplateArugments>::StaticVarName;
使用static_assert执行编译阶段检查
tatic_assert是C++11新增的一项功能,让您能够在不满足指定条件时禁止编译。语法如下:
static_assert(expression being validated, "error message when check fails"
要禁止针对类型int实例化模板类,可使用static_assert(),并将sizeof(T)与sizeof(int)进行比较,如果它们相等,就显示一条错误消息:
static_assert(sizeof(T)!=sizeof(int), "No int please!");
示例代码如下
usingnamespacestd; template<typenameT>classeverythingbutInt{ public: everythingbutInt() { static_assert(sizeof(T) !=sizeof(int), "Not int please!"); } }; intmain() { everythingbutInt<int>test; return0; }