类属机制 在程序设计语言中,参与运算的所有对象的类型在编译时就可以确定,编译程序对类型进行严格 査,于是可以在程序运行前就可以查出错误,提高了程序的可靠性。但是这样做同时有带来副 作用。链表,堆栈,集合等常用数据结构在各种软件中都会用到,它们有可能存放各种类型的数据 由于这类数据结构存放的元素类型不同,程序员不得不为每一种数据类型编写相似的程序代码。这 样就增加了程序代码。如何解决这种类型的严格与灵活的问题,不同的语言采用了不同的方法。理 想的方法是将数据类型作为类的参数,这种机制称为类属 高版本的C艹语言中均加入了类属机制。在C艹+中,类属被称为模板,模板按照其用途可分为函 数模板和类模板两种类型。模板中的参数类型没有确定,只有经过实例化,变为一般的函数(C艹称 其为模板函数)或一般的类(C++称其为模板类),模板才有意义。 板 模板函数 模板类 对象 对象
类属机制 在程序设计语言中,参与运算的所有对象的类型在编译时就可以确定,编译程序对类型进行严格 的检查,于是可以在程序运行前就可以查出错误,提高了程序的可靠性。但是这样做同时有带来副 作用。链表,堆栈,集合等常用数据结构在各种软件中都会用到,它们有可能存放各种类型的数据。 由于这类数据结构存放的元素类型不同,程序员不得不为每一种数据类型编写相似的程序代码。这 样就增加了程序代码。如何解决这种类型的严格与灵活的问题,不同的语言采用了不同的方法。理 想的方法是将数据类型作为类的参数,这种机制称为类属。 高版本的 C++语言中均加入了类属机制。在 C++中,类属被称为模板,模板按照其用途可分为函 数模板和类模板两种类型。模板中的参数类型没有确定,只有经过实例化,变为一般的函数(C++称 其为模板函数)或一般的类(C++称其为模板类),模板才有意义。 模 板 模板函数 模 板 类 对象 对象 对象
函数模板 函数模板是一种很有用的语言设施,它提供了描述通用操作的高级手段,这种机制可用一种抽象 数据类型来设计一个通用的算法。 函数模板的一般性语法为: 返回值类型函数名(模板函数形参表) ∥函数体 其中,模板形参表表示被替换的模板参数,各模板参数之间用“,”号分开。模板函数形参表表 示函数所具有的参数,它不仅包含模板形参表的内容,而且还可具有一般的类型参数 下面设计一个将任何类型的两个数值进行交换的函数Swap(x,y) C艹属于强类型语言,它要求参数的类型在编译时必须确定。为了完成上面的要求,可以通过 重载设计出Swap(x,y) 例 void Swap(int &x, int &. y)
函数模板 函数模板是一种很有用的语言设施,它提供了描述通用操作的高级手段,这种机制可用一种抽象 数据类型来设计一个通用的算法。 函数模板的一般性语法为: template 返回值类型 函数名(模板函数形参表) { //函数体; } 其中,模板形参表表示被替换的模板参数,各模板参数之间用“,”号分开。模板函数形参表表 示函数所具有的参数,它不仅包含模板形参表的内容,而且还可具有一般的类型参数。 下面设计一个将任何类型的两个数值进行交换的函数 Swap(x, y)。 C++属于强类型语言,它要求参数的类型在编译时必须确定。为了完成上面的要求,可以通过 重载设计出 Swap(x, y) 例 void Swap (int &.x, int &.y) { int t;
void Swap(long &.x, long &. y) C++提供了另一种更高级的机制,即用函数模爆来解决这一问题。在函数模板中,类型本身可 以作为一个参数。Swap(x,y)函数用函数模板可定义如下: Swap hpp Void swap(T&x, T&y)
t=x; x=y; y=t; } void Swap (long &.x, long &.y) { long t; t=x; x=y; y=t; } C++提供了另一种更高级的机制,即用函数模爆来解决这一问题。在函数模板中,类型本身可 以作为一个参数。Swap(x, y)函数用函数模板可定义如下: Swap.hpp Template Void swap (T &.x, T &.y) {
该定义说明,无论参数T是什么类型,函数Swap(x,y)都表示将T的两个变量(或对象)的 值进行交换。函数Swap(T&x,T&y)是一个抽象的函数,在进行具体的数据交换之前必须将 其参数T实例化为某个具体的类型,如或用户自定义的类等类型后,该函数才有意义。C++称其 为函数模板,它代表了一类函数的家族。当用某个具体的类型将模板参数实例化后,该函数就变 成了一个具体的函数。将T实例化的类型称为模板实参,用模板实参实例化函数模板得到的函数 称为模板函数 按函数模板的使用形式可将其分为两种方式。 一种为显式方式 Swap( int&, int&); ongc.Iong 另一种为隐式方式:
T t; T=x; x=y; y=t; } 该定义说明,无论参数 T 是什么类型,函数 Swap(x, y)都表示将 T 的两个变量(或对象)的 值进行交换。函数 Swap(T &.x, T &.y)是一个抽象的函数,在进行具体的数据交换之前必须将 其参数 T 实例化为某个具体的类型,如或用户自定义的类等类型后,该函数才有意义。C++称其 为函数模板,它代表了一类函数的家族。当用某个具体的类型将模板参数实例化后,该函数就变 成了一个具体的函数。将 T 实例化的类型称为模板实参,用模板实参实例化函数模板得到的函数 称为模板函数。 按函数模板的使用形式可将其分为两种方式。 一种为显式方式: Swap( int&, int&); Swap(long&,long&) 另一种为隐式方式:
重载函数模板 同一般的函数一样,函数模板也可以重载。例 ax hpp TYPE max(TYPE a, TYPE b) return( a>b)? A: b template TYPE max(TYPE a, TYPE b, TYPE c) t=(a>b)? a: b return(t>c)?t:c
int I=10, j=20; Swap(I, j); 重载函数模板 同一般的函数一样,函数模板也可以重载。 例 //max.hpp template TYPE max (TYPE a, TYPE b) { return ( a>b)? A: b; } template TYPE max (TYPE a, TYPE b, TYPE c) } TYPE t; t= (a > b) ? a: b; return (t > c) ? t: c;
一般地,这种重载是指参数的个数不同,而不是参数的类型不同 C+中重载函数的调用次序为 1)寻找一个参数完全匹配的函数,若找到,就调用之。 2)否则寻找一个函数模板,将其实例化产生一个匹配的模板函数,若找到,就调用之 3)否则寻找重载函数中有无通过类型转换后产生参数匹配的函数,若有,则调用之。 类模板 与函数模板一样,在设计类时,也往往遇到仅由于类型不一样而不得不重复地设计出 很多形式相象的类。基于同样的原因,C++引入了类模板机制。 类模板的一般性语法为 template class模板形参表> class类模板名{ ∥类体 其中,模板形参表同函数模板中的说明,类体中要用到这些模板参数
} 一般地,这种重载是指参数的个数不同,而不是参数的类型不同。 C++中重载函数的调用次序为: 1)寻找一个参数完全匹配的函数,若找到,就调用之。 2)否则寻找一个函数模板,将其实例化产生一个匹配的模板函数,若找到,就调用之。 3)否则寻找重载函数中有无通过类型转换后产生参数匹配的函数,若有,则调用之。 类模板 与函数模板一样,在设计类时,也往往遇到仅由于类型不一样而不得不重复地设计出 很多形式相象的类。基于同样的原因,C++引入了类模板机制。 类模板的一般性语法为: template class 类模板名 { // 类体; }; 其中,模板形参表同函数模板中的说明,类体中要用到这些模板参数
类模板的成员函数的体外定义,每个前面都必须用与声明该类模板一样的 template加以声明。 类模板必须用类型参数将其实例化为具体的模板类后,才能用来生成对象。一般地,其形式 可表示为: 类模板名对象名(值实参表) 其中,类型实参表表示将类模板实例化为一般的类时所用到的类型(包括系统固有的类型和 用户自定义的类型),值实数表表示将该模板类实例化为对象时其构造函数所用到的变量 个模板类可用来实例化多个模板类 例]栈类模板 //stack. hpp template <class class Stack' Int top Int size. int isEmpty()return (top<0)? 1: 0, 1
类模板的成员函数的体外定义,每个前面都必须用与声明该类模板一样的 template 加以声明。 类模板必须用类型参数将其实例化为具体的模板类后,才能用来生成对象。一般地,其形式 可表示为: 类模板名 对象名 (值实参表); 其中,类型实参表表示将类模板实例化为一般的类时所用到的类型(包括系统固有的类型和 用户自定义的类型),值实数表表示将该模板类实例化为对象时其构造函数所用到的变量。一 个模板类可用来实例化多个模板类。 例] 栈类模板 //stack.hpp template class Stack{ private: T*date; Int top; Int size; int isEmpty ( ) {return (top < 0) ? 1:0;}
Int isfull()(return top-size ?1: 0, Stack(int n)(date=new Tn]: size=n, top=0, 3 -Stack(( delete [ date, j Stack.中的push和pop成员函数的体外定义 /stack. cpp void Stack. pop(T a) if(isfull () cout<< stack overflow \n
Int isfull ( ) {return top==size} ?1: 0;} Public: Stack (int n) {date=new T[n]; size=n; top=0;} ~Stack ( ){delete []date;} void pop(T n); T push( ); }; Stack中的 push 和 pop 成员函数的体外定义 //stack.cpp //include // “stack.hpp” template void Stack:: pop(T a) { if (isfull ( ) ) { cout<<”stack overflow\n”; return;
(date+top++Fa; retum if(isempty()) cout<<"stack underflow return(*(date+top)), 与函数模板不同,类模板必须进行显式的实例化声明。 综上所述,类模板机制允许用户定义一种具有相似行为的类的模式,它要求这些类具有 相通的操作(包括内部操作和外部操作),并且要求这些操作的算法也是相同的
} * (date+top++)=a; return; } template inline T Stack:: push( ) { if (isempty( )) { cout<<”stack underflow\n”; } return (* (date+top)); } 与函数模板不同,类模板必须进行显式的实例化声明。 综上所述,类模板机制允许用户定义一种具有相似行为的类的模式,它要求这些类具有 相通的操作(包括内部操作和外部操作),并且要求这些操作的算法也是相同的
类模板的友元 类模板的友元函数大致可分为三种情况 1)一般的类模板友元函数:这种友元函数不包含任何类型的模板参数,定义和作用与 般类的情况一样 2)封闭型的类模板友元函数:同模板类中的其他成员函数一样,该类的友元函数也包含 模板参数。当用类型参数将类模板实例化为某个具体的模板类时,该类模板所包含的友元 函数也将随之实例化,就如同一般的成员函数一样 3)开放型的类模板友元函数:它的参数中包含了自己定义的函数模板的模板参数,而相 关类模板的参数可以出现,也可以不出现 例 template class af friend void foo( 在这里,foo()模板函数的任何一个实例化函数模板均是A模板类的任何一个类模板的友元 同时,A模板类的任何一个类模板均是foo(模板函数的任何一个函数模板的友元。这样在 A的类模板与foo()的函数模板之间形成了一个多对多的对应关系
类模板的友元 类模板的友元函数大致可分为三种情况 1)一般的类模板友元函数:这种友元函数不包含任何类型的模板参数,定义和作用与 一般类的情况一样。 2)封闭型的类模板友元函数:同模板类中的其他成员函数一样,该类的友元函数也包含 模板参数。当用类型参数将类模板实例化为某个具体的模板类时,该类模板所包含的友元 函数也将随之实例化,就如同一般的成员函数一样。 3)开放型的类模板友元函数:它的参数中包含了自己定义的函数模板的模板参数,而相 关类模板的参数可以出现,也可以不出现。 例 template class a{ template class friend void foo(T2 vt2); …. } 在这里,foo( )模板函数的任何一个实例化函数模板均是 A模板类的任何一个类模板的友元; 同时,A模板类的任何一个类模板均是 foo( )模板函数的任何一个函数模板的友元。这样在 A的类模板与 foo( )的函数模板之间形成了一个多对多的对应关系