第八章_函数模板与类模板

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

4)函数模板也可以重载。 例:函数模板重载。 template <typename Type> Type min(Type x,Type y) { return (x<y)?x:y; } template <typename Type> Type min(Type x,Type y,Type z) { Type t; t=(x<y)?x:y; return (t<z)?t:z; }
int main() { int i1=10,i2=56; double dl=50.34,d2=23,56; char c1='k',c2='c'; cout<<"较小的整数是:"<<min(i1,i2)<<endl; cout<<"较小的双精度型数是:"<<min(d1,d2)<<endl; cout<<"较小的字符串是:"<<min(c1,c2)<<endl; return 0; }
函数模版:建立一个通用函数,其函数返回 类型和形参类型不具体指定,用一个虚拟 的类型来代表,这个通用函数就称为函数 模版。
函数模板的一般说明形式如下: template <typename 类型参数> 返回类型 函数名(模板形参表) { 每个类型参数之前都有一个关键字class 函数体 或typename。多个类型参数之间用逗号分隔。 作用:说明其后的参数是一个虚拟的类型名 }
函数模板定义时应注意的问题: 1)在template语句与函数模板定义之间不许 有别的语句。 template<class T> int i; //错误 T min(T x,T y) { return (x<y)?x:y;}
2)调用模板函数时,应保证函数的实参类型与类型参数完 全匹配。函数模板在实例化过程中不做任何类型转换。 例如:已知函数模板max的两个形参都是类型参数TYPE类型 的,则以下两个应用错误: max(10, 10.5);
8.3 类模板与模板类
类模板:建立一个通用类,其数据成 员,成员函数的返回类型和形参类型不具 体指定,用一个虚拟的类型来代表。 使用类模版定义对象时,系统会根据 实参的类型来取代类模版中虚拟类型,从 而实现不同类的功能。
定义一个类模板,其格式如下: template <typename 类型参数> class 类名 { //… 类模板定义体 };
template <class Type> //每个成员函数都要加上模板声明 void stack<Type>::push(Type ob) //类名为stack<Type> { if (tos==size) { cout<<"stack is full"; return ; } stck[tos]=ob; tos++; } template <class Type> Type stack <Type>::pop(){ if (tos==0) { cout<<"stack is empty"; return 0; } tos--; return stck[tos]; }
【例8.1】 函数模板的使用。 #include <iostream.h> template < class T> T max(T x,T y) { return (x>y) ? x:y; } main() { int i1= 10, i2=56; float f1=12.5, f2=24.5; double d1=50.344, d2=4656.346; char c1='k ',c2='n'; cout<<"The max of i1,i2 is: "<<max(i1,i2)<<endl; cout<<"The max of f1,f2 is: "<<max(f1,f2)<<endl; cout<<"The max of d1,d2 is: "<<max(d1,d2)<<endl; cout<<"The max of c1,c2 is: "<<max(c1,c2)<<endl; return 0; }
6)在函数模板定义template中给出的每一个形式
类属参数都必须在函数形参表中至少出现一次: –如: template <class T1, class T2>
void fun(T1 x, T2 y) { …… }
–错误的用法 ㊀template <class TYPE> TYPE* func() { ……} ㋥template <class TYPE> void func() { TYPE obj; …… }
第8章 模

8.1 模板的概念
问题的引入: 一些函数的功能相同,唯一的区别只在于处理对象的数据 类型不同,若用函数重载实现,则需编写多个函数: 例: int max(int i, int j) { return i>j?i:j;} 这些函数执行的功能是相同的,只是参数类型和函数返 float max(float i, float j) 回类型不同,能否为上述这些函数只写出一套代码呢? { return i>j?i:j;} char max(char i,char j) { return i>j?i:j;}
பைடு நூலகம்
函数模板参数表的类型参数可以用于函数返 回值,也可用于函数参数表及函数体中。
例如,将求最大值函数max()定义成函数模板,如下所示: template <class T> T max(T x, T y) { return (x > y) ? x : y; } 也可以定义成如下形式: template <typename T> T max(T x,T y) { return (x>y)?x:y; } 其中,T为类型参数,它既可取系统预定义的数据类型,又可以 取用户自定义的类型。
int main() { //定义字符堆栈 stack <char> s1,s2; //创建两个模板参数为char型的对象 int i; s1.init(); s2.init(); s1.push('a'); s2.push('x'); s1.push('b'); s2.push('y'); s1.push('c'); s2.push('z'); for(i=0;i<3;i++) cout<<"pop s1: "<<s1.pop()<<endl; for(i=0;i<3;i++) cout<<"pop s2: "<<s2.pop()<<endl;
5)函数模板与同名的非模板函数也可以重 载。调用顺序: 1)参数完全匹配的非模板函数; 2)函数模板,将其实例化,产生模板函 数; 如果以上2种情况都未找到匹配函数,则 按出错处理。
#include<iostream.h> template <typename AT> AT min(AT x,AT y) { cout<<"调用模板函数"; return (x<y)?x:y; } int min(int x,int y) { cout<<"调用非模板函数"; return (x<y)?x:y; }
//一个实参是整型,另一个是double型,类型不同
max(10, obj1);
//一个实参是整型,另一个是MY_CLASS类型,都无法实例化
3)在函数模板中允许使用多个类型参数。在template定义 部分的每个类型参数前必须有关键字class(或typename)。
例:有两个类型参数的函数模板。 #include<iostream.h> template<typename type1,typename type2> void myfunc(type1 x,type2 y) { cout<<x<<’ ’<<y<<endl; } int main() { myfunc(10,"hao"); myfunc(0.123,10); return 0; }
–说明: – (1) 函数模板本身不是函数,是生 成函数的“模板”。经实例化后才得到 真正的函数。 – (2)实例化是指用某一具体的实际 数据类型替代模板中的类型参数的过程。
8.2.2 函数模板的使用
函数模板的使用就是将函数模板的实例 化为具体的函数。函数模板的实例化由编 译器来完成。编译系统根据函数调用的实 际参数类型自动完成函数模板的实例化。 当编译系统发现有一个函数调用: 函数名(模板实参表); 时,将根据模板实参表中的类型生成一个 函数即模板函数。该模板函数的函数体与 函数模板的函数定义体相同。
例:定义类模板CThree储存三个成员变量,返回这三个成员 变量的和。
template <class T> class CThree{ public: CThree(T t1,T t2,T t3):a(t1),b(t2),c(t3) {} T sum() { return a+b+c;} private: T a,b,c; };
T max(T x,T y) {return (x>y)?x:y;}
模板运算对象的类型不是实际的数据 类型,而是一种参数化的类型,即是把 数据类型作为模板的参数。
模板是实现代码重用机制的一种工具。
模版 (函数模版和类模版) 实例化
实例化 模版类
模版函数
实例化 对象
8.2 函数模板与模板函数
8.1 函数模板的声明
int int_array[]={1,2,3,4,5,6}; double d_array[]={1.1,2.2,3.3,4.4,5.5}; main() { int itotal=sum(int_array,6); double dtotal=sum(d_array,5); cout<<"itotal= "<<itotal<<endl; cout<<"dtotal= "<<dtotal<<endl; }
总结:函数模板提供了一类函数的抽象,代表 了一类函数。模板函数表示一具体的函数。
函数模版 max(T,T)
实例化 实例化
实例化
模版函数 max(int,int)
模版函数 max(double,double)
模版函数 max(char,char)
例:有关指针的函数模板举例。
#include <iostream.h> template <class AT> AT sum(AT *array,int size=0) { AT total=0; for(int i=0;i<size;i++) total+=array[i]; return total; }
类模板 CThree<T> 实例化 模板类 CThree<int>
实例化
模板类 CThree<float>
实例化
对象a
实例化
对象b
例: 栈类模板的使用。 #include<iostream.h> const int size=10; template<class Type> //声明一个类模板 class stack { public: void init(){ tos=0; } void push(Type ch); //参数取Type类型 Type pop(); //返回类型取Type类型 private: Type stck[size]; //数组的类型为类型参数Type, int tos; };
说明: (1)定义模板时应至少确定一个模板参数; (2)类模板的定义格式与类的定义格式相同, 包含说明部分和实现部分; 在类体外定义时,其格式如下: template <模板参数表T> 返回值类型 类名<T>::函数名(参数表) {函数体}
template <class T> class CThree{ public: CThree(T t1,T t2,T t3); T sum(); private: T a,b,c; }; template <class T> CThree<T>::CThree(T t1,T t2,T t3) { a=t1;b=t2;c=t3;} template <class T> T CThree<T>::sum() { return a+b+c;}
类模板不是代表一个具体的、实际的类, 而是代表着一类类。实际上,类模板的使 用就是将类模板实例化成一个具体的类 , 即为模板类。它的格式为:
类模板名 <实际的类型> 对象名; 类模板名 <实际的类型> 对象名(参数);
int main() { CThree <int> a(3,5,1); CThree <float> b(3.3,5.1,1.2); cout<<“三个整数的和是”<<a.sum()<<endl; cout<<“三个实数的和”<<b.sum()<<endl; return 0; }
相关文档
最新文档