第十章模板 模板( Template)是C++支持参数化多态的工具,使用 模板可以减少程序员的重复劳动,使程序员可以建立具有通用 类型的函数库和类库 所谓模板是一种使用无类型参数来产生一系列函数或类的 机制,是C++的一个重要特性。它的实现,方便了更大规模的 软件开发。 若一个程序的功能是对某种特定的数据类型进行处理,则 可以将所处理的数据类型说明为参数,以便在其他数据类型的 情况下使用,这就是模板的由来。模板是以一种完全通用的方 法来设计函数或类而不必预先说明将被使用的每个对象的类型。 通过模板可以产生类或函数的集合,使它们操作不同的数据类 型,从而避免需要为每一种数据类型产生一个单独的类或函数
第十章 模板 模板(Template)是C++支持参数化多态的工具,使用 模板可以减少程序员的重复劳动,使程序员可以建立具有通用 类型的函数库和类库。 所谓模板是一种使用无类型参数来产生一系列函数或类的 机制,是C++的一个重要特性。它的实现,方便了更大规模的 软件开发。 若一个程序的功能是对某种特定的数据类型进行处理,则 可以将所处理的数据类型说明为参数,以便在其他数据类型的 情况下使用,这就是模板的由来。模板是以一种完全通用的方 法来设计函数或类而不必预先说明将被使用的每个对象的类型。 通过模板可以产生类或函数的集合,使它们操作不同的数据类 型,从而避免需要为每一种数据类型产生一个单独的类或函数
10.1模板攏魯 为什么要引进模板概念: 例如,设计一个求两参数最大值的函数,不使用模板时,需要定 义四个函数: int max int a, int btreturn(a>b?a, b;3 long max(long a, long btreturn (a>ba, biy double max double a, double bireturn(a>ba, b;y char max(char a, char btreturn(a>b?a, b;y 我们从上可以看到,这四个函数的功能都是一样的,只不过 函数的参数类型和返回类型不一样,显然这样设计就显的程序代 码很冗余,那怎么解决该问题呢: 采用宏定义:# define maxi(xy)(x>y)?(x):(y) 在C++中,宏替换不进行任何类型检查,则显然不符合 C++的强类型语言,即数据类型必须强制说明和检查。不鼓励 使用宏定义,解决这问题可以用C++的模板函数解决
10.1 模板概念 为什么要引进模板概念: 例如,设计一个求两参数最大值的函数,不使用模板时,需要定 义四个函数: int max(int a, int b) {return(a>b)?a,b; } long max(long a, long b) {return(a>b)?a,b; } double max(double a, double b) {return(a>b)?a,b; } char max(char a, char b) {return(a>b)?a,b; } 我们从上可以看到,这四个函数的功能都是一样的,只不过 函数的参数类型和返回类型不一样,显然这样设计就显的程序代 码很冗余,那怎么解决该问题呢: 采用宏定义:#define max(x, y) ((x>y)?(x):(y)) 在C++中,宏替换不进行任何类型检查,则显然不符合 C++的强类型语言,即数据类型必须强制说明和检查。不鼓励 使用宏定义,解决这问题可以用C++的模板函数解决
10.1模板攏魯 若使用模板函数,则只需定义一个函数模板: template type max type a, type b) d return(a>ba, b;y c++程序由类和函数组成,模板也分为类模板(cass emplate)和函数模板( function template)。在说明了 个函数模板后,当编译系统发现有一个对应的函数调用时, 将根据实参中的类型来确认是否匹配函数模板中对应的形参, 然后生成一个重载函数。该重载函数的定义体与函数模板的函 数定义体相同,它称之为模板函数( template function)。 同样,在说明了一个类模板之后,可以创建类模板的实 例,即生成模板类
10.1 模板概念 C++程序由类和函数组成,模板也分为类模板(class template)和函数模板(function template)。在说明了 一个函数模板后,当编译系统发现有一个对应的函数调用时, 将根据实参中的类型来确认是否匹配函数模板中对应的形参, 然后生成一个重载函数。该重载函数的定义体与函数模板的函 数定义体相同,它称之为模板函数(template function)。 同样,在说明了一个类模板之后,可以创建类模板的实 例,即生成模板类。 若使用模板函数,则只需定义一个函数模板: template type max(type a, type b) { return(a>b)?a,b; }
10.2搬模板 C++提供的函数模板可以定义一个对任何类型变量进行操 作的函数,从而大大增强了函数设计的通用性。使用函数模板 的方法是先说明函数模板,然后实例化成相应的模板函数进行 调用执行 函数模板说明: 函数模板的一般说明形式如下: template (模板函数形参表) //函数定义体; 其中, template是定义模板的关键字,可 以包含基本数据类型,也可以包含类类型,如果类型形参多于 个,则每个类型参数都要使用 class,并且它们之间用逗号隔 开。中的参数必须是惟一的
10.2 函数模板 C++提供的函数模板可以定义一个对任何类型变量进行操 作的函数,从而大大增强了函数设计的通用性。使用函数模板 的方法是先说明函数模板,然后实例化成相应的模板函数进行 调用执行。 函数模板说明: 函数模板的一般说明形式如下: template (模板函数形参表) { //函数定义体; } 其中,template是定义模板的关键字,可 以包含基本数据类型,也可以包含类类型,如果类型形参多于 一个,则每个类型参数都要使用class,并且它们之间用逗号隔 开。中的参数必须是惟一的
10.2画模板 函数模板定义不是一个实实在在的函数,编译系统不为 其产生任何执行代码。该定义只是对函数的描述,表示它每 次能单独处理在类型形式参数表中说明的数据类型。 # include≤ iostream.k template T max(TX, Ty d return(x>y?x:yi 结果 maino 3.4 d int x=3,y =4; double a= 1.2, b= 3.4 cout < max x, y<< endi cout < max(a, b)<< end; }
10.2 函数模板 函数模板定义不是一个实实在在的函数,编译系统不为 其产生任何执行代码。该定义只是对函数的描述,表示它每 次能单独处理在类型形式参数表中说明的数据类型。 #include template T max(T x, T y) { return(x>y?x:y); } main() { int x = 3, y = 4; double a = 1.2, b = 3.4; cout << max(x, y) << endl; cout << max(a, b) << endl; } 结果: 4 3.4
例:编写一个对具有n个元素的数组a[]求最小值的程序, 要求将求最小值的函数设计成函数模板。 #include void maino template i int a[]=t1 3, 0,2, 7, 6,4, 5,2] T min(t all, int n) double b[]={12-346898} d int ii couta[i] < min (b, 4)<< endl; minv=ali]; return minv: 此程序的运行结果为: a数组的最小值为:0 b数组的最小值为:34心
#include template T min(T a[], int n) { int i; T minv=a[0]; for(i=1; ia[i]) minv=a[i]; return minv; } 例:编写一个对具有n个元素的数组a[ ]求最小值的程序, 要求将求最小值的函数设计成函数模板。 void main() { int a[]={1,3,0,2,7,6,4,5,2}; double b[]={1.2,-3.4,6.8,9,8}; cout<<”a 数组的最小值为:” << min(a, 9)<< endl; cout<<”b数组的最小值为:” << min(b, 4)<< endl; } 此程序的运行结果为: a数组的最小值为:0 b数组的最小值为:-3.4
10.2菡数模板 使用函数模板: 函数模板是对一组函数的描述说明,不直接产生可执行的 代码,所以不能直接执行,而模板函数是某个函数模板的实例化 它是可以执行的。一个函数模板可以产生多个模板函数。 当编译系统发现有一个函数调用:();时,将根据中的类型生成一个重载函数即模板 函数。该模板函数的定义体与函数模板的函数定义体相同,而 形参表>的类型则以的实际类型为依据 对模板函数的说明和定义必须是全局作用域。模板不能被说 明为类的成员函数。 模板函数有一个特点,虽然模板参数T可以实例化成各种类 型,但是采用模板参数T的各参数之间必须保持完全一致的类型。 模板类型并不具有隐式的类型转换,例如在int与char之间、 foat与int之间、foat与 double之间等的隐式类型转换。而这 种转换在C++中是非常普遍的 心[u
10.2 函数模板 使用函数模板: 函数模板是对一组函数的描述说明,不直接产生可执行的 代码,所以不能直接执行,而模板函数是某个函数模板的实例化, 它是可以执行的。一个函数模板可以产生多个模板函数。 当编译系统发现有一个函数调用:();时,将根据中的类型生成一个重载函数即模板 函数。该模板函数的定义体与函数模板的函数定义体相同,而的类型则以的实际类型为依据。 对模板函数的说明和定义必须是全局作用域。模板不能被说 明为类的成员函数。 模板函数有一个特点,虽然模板参数T可以实例化成各种类 型,但是采用模板参数T的各参数之间必须保持完全一致的类型。 模板类型并不具有隐式的类型转换,例如在int与char之间、 float与int之间、float与double之间等的隐式类型转换。而这 种转换在C++中是非常普遍的
10.2数模板 模板函数也遵循普通函数重载规则支持重载,一般来说, 重载函数主要解决函数名相同、算法相同、但参数个数或类型 不同的问题,而函数模板只解决函数名相同、算法相同、参数 个数也相同,仅类型不同的问题。并且要注意函数模板和重载 函数的二义性问题 #include char *max(char *v1, char *v2) template ireturn(strcmp(x, y)>0?x:y);3 Type max(Type v1, Type v2) fi return(v1> v2?v1: v2); } 所以,当一般函数与同名模板函数同 时存在时,调用顺序是一般函数优先。 void maino d cout<<max (100, 300)<<end; cout<<max(32. 1, 3.14<<endl; cout<<max( Zhang"")<<endl;
10.2 函数模板 模板函数也遵循普通函数重载规则支持重载,一般来说, 重载函数主要解决函数名相同、算法相同、但参数个数或类型 不同的问题,而函数模板只解决函数名相同、算法相同、参数 个数也相同,仅类型不同的问题。 并且要注意函数模板和重载 函数的二义性问题。 #include template Type max(Type v1, Type v2) { return(v1 > v2?v1:v2); } void main() { cout0?x:y);} 所以,当一般函数与同名模板函数同 时存在时,调用顺序是一般函数优先
10.2数模板 下面我们编写一个通用的排序程序: include //10-2. cpp template maino void GeneralSort(T *a, int n) f int i, x[I=15, 2,8,7)i inti, jiT比 double y[]=<2.8, 1.2, for(i=1;i<n-1;i++){ 33,06} k GeneralSort(x, 4); for(=i+1;j<n;j+十) General Sort(y, 4) if(aD]<a[k])k=j;for(i=0; i< 4; i++) f(k!=i){ cout < x[i]<< tt= alkli cout < enda akkI= alil for(i=0;i<4;i++ a[i]= tt;y cout < y[]<< cout < enda }
10.2 函数模板 下面我们编写一个通用的排序程序: #include // 10-2.cpp template void GeneralSort(T *a, int n) { int i, j; T tt; for(i=1; i < n-1; i ++) { k = i; for(j=i+1; j <n; j ++) if(a[j] < a[k]) k = j; if(k != i) { tt = a[k]; a[k] = a[i]; a[i] = tt;} } } } main() { int i, x[] = {5, 2, 8, 7}; double y[] = {2.8, 1.2, 3.3, 0.6}; GeneralSort(x, 4); GeneralSort(y, 4); for(i=0; i < 4; i ++) cout << x[i] << “ “; cout << endl; for(i=0; i < 4; i ++) cout << y[i] << “ ”; cout << endl; }
10.2数模板 函数模板方法克服了C语言解决上述问题时用大量不同 函数名表示相似功能的坏习惯;克服了宏定义不能进行参数 类型检查的弊端;克服了C++函数重载用相同函数名字重 写几个函数的繁琐。因而,函数模板是C++中功能最强的 特性之一,具有宏定义和重载的共同优点,是提高软件代码 重用率的重要手段
10.2 函数模板 函数模板方法克服了C语言解决上述问题时用大量不同 函数名表示相似功能的坏习惯;克服了宏定义不能进行参数 类型检查的弊端;克服了C++函数重载用相同函数名字重 写几个函数的繁琐。因而,函数模板是C++中功能最强的 特性之一,具有宏定义和重载的共同优点,是提高软件代码 重用率的重要手段