/**/ /**/ /**/ /*********************************************************************** <模板> *模板是一种参数化的类或函数,也就是类的形态或者函数的形态可以被参数改变.***********************************************************************/ /**/ /**/ /**/ /*********************************************************************** <模板函数> */ template < class T > T funname(para type) /**/ /**/ /**/ /*自我理解:* 如果要计算int型和float型数组的平均值,可以分别写int_average(int nVal,*int size)和*float_average(int nVal,int size)两个函数,但其实它们里面的步骤是一*样的,只是数据类型*不同,如果使用模板,就不需要这么麻烦了。***********************************************************************/ // 例1: template < class T > average(T * array, int size) ... ... { T sum = 0; for(int i=0;i<size;i++) sum += array[i]; T avg = sum/size; return avg; } ; // "<class T>"告诉编译器"T"是函数使用的数据类型。 // 提示:模板函数最好写在头文件中,但必须要写在main()前面 // 例2: template < class T > T max(T x,T y) // 传入的参数改必须是同类型的 ... ... { return (x>y) ? x:y; } void main() ... ... { double a = 50.235; double b = 50.234; double c = max(a,b); cout<<"最大值="<<c<<endl; } // 函数模板经实例化所生成的具体函数叫"模板函数"; // 例如例1,可以实例化成 average(int,int)、average(float,float)、average(char,char) 等等... // 每一个模板形参前必须有"class"关键字! // 在template语句与函数模板语句之间不允许有别的语句; /**/ /**/ /**/ /*********************************************************************** <多类型模板函数> ** 如上题数组,若数组中所有元素之和超过类型范围怎么办?可用多类型*函数模板解决 ***********************************************************************/ // 例: template < class T1, class T2 > T1 average(T1 * array,T2, int size) // 声明函数模板 ... ... { T2 sum = 0; for(int i=0;i<size;i++) sum+=array[i]; return(sum/i); } void main() ... ... { __int16 intArray[]=......{10000,20000,30000}; // 范围 -32768 - 32767 cout<<"整数平均值="<<::average(intArray,0,3)<<endl; } /**/ /**/ /**/ /* 自我理解 此例中,当T1接收了__int16 intArray[]后,它俨然就成了__int16型了,但要命的是,数组中的数字相加后,会超界,so...再定义一个T2,用T2来接收相加后的的数据,T2会根据数据的大小来确定自己的类型。 */ /**/ /**/ /**/ /*********************************************************************** <模板函数的重载> * 因为模板函数需要接收同类型的参数,要是参数类型不一致怎么办?可以使用函数重载.***********************************************************************/ template < class T > T max(T x,T y) // 传入的参数改必须是同类型的 ... ... { return (x>y) ? x:y ; } int max( int x , char y) // 重载函数 max,一个整型参数,一个字符型参数 ... ... { return (x>y) ? x:y ; } void main() ... ... { int a = 55;// int b = 66; char b = 'A'; //ASCII 码 65 cout<<"最大值="<<max(a,b)<<endl; //此处将调用重载函数 } /**/ /**/ /**/ /*********************************************************************** <类模板> ***********************************************************************/ const int size = 10 ; template < class T > class stack ... ... { T stck[size]; //模板定义数组的数据类型 public: //若成员函数中使用了模板,则此函数需要在类体外定义!!! void push(T ch); //模板定义形参类型 T pop(); //模板定义返回类型 } ; template < class T > // 注意:在类体外实现成员函数时的写法!!! void stack < T > ::push(T ob) ... ... { } template < class T > // 注意:在类体外实现成员函数时的写法!!! T stack < T > ::pop() ... ... { T a = 0; return a; } void main() ... ... { stack<int> a; //对象的定义 //stack<int> a,b; //stack<double> b; } /**/ /**/ /**/ /*********************************************************************** <多参数类模板> * template <class T,T t> 或者 template <class T,int size>* 参数的名字在整个模板的作用域内都有效,类型参数可以作用作用域变量的类型,数值型*参数可以参与计算,就像使用一个普通常数一样(例如 cout<<t<<endl;)***********************************************************************/ // 多参数模板 template < class T, int size > // 第一个参数是类型,第二个参数是数值(必须是常量) class stack ... ... { T stck[size]; public: void push(T x); T pop(); void print() ......{ cout<<size<<endl; } } ; template < class T, int size > // 注意写法!!! void stack < T,size > ::push(T x) ... ... { } template < class T, int size > // 注意写法!!! T stack < T,size > ::pop() ... ... { T a = 0; return a; } void main() ... ... { stack<int,10> a1,a2; //合法,对象的定义 int x = 100; stack<int,x> b1; //不合法,x必须是常量 const int y = 100; stack<int,y> c1; //合法. a1.print(); // stack<double,5> b1,b2; //对象的定义 } /**/ /**/ /**/ /***********************************************************************模板总结:* 模板提供了代码复用.在使用模板时首先要实例化,即生成一个具体的函数或类.函数模*板的实例化是隐式实现的,即由编译系统根据对具体模板函数(实例化后的函数)的调用来进*行相应的实例化,而类模板的实例化是显示进行的,在创建对象时由程序指定.** 以前我一直以为模板的方法全部都是隐含为inline(内联,就是函数体定义在类之外,提高*函数的执行效率)的,其实并非如此(Thinking C++[2]中有提到模板的non-inline function).所以*我们一般在后缀为 .i 或者 .inl的文件中完成模板类方法的实现.*例: //in temp.h //in temp.inl * template<class T> template<class T>* class Temp void Temp<class T>::print() * { {...}* public:* void print();* }* #include "temp.inl"**语法检查* 对模板语汇法的检查会被延迟到使用的时刻,而不像一般的类或函数在编译器读到时就*检查,所以如果你定义了一个模板,且语法错误,但你却没有去用它,编译时不会报错.**继承* 模板类和普通的类一样,也可以有派生类.且它的基类和派生类既可以是模板类,也可以不*是模板类.* class Abase * {...};* template<classT> * class A:public Abase* {...};***********************************************************************/ // 模板小练习 template < class T > T sum(T x,T y) ... { return x+y;} void main() ... { int a = 100; int b = 200; int c = sum(a,b); cout<<"总和="<<c<<endl;} template < class T1, class T2 > T1 average(T1 * x,T2 y, int size) ... { T2 sum = 0; for(int i=0;i<size;i++) ...{ sum += x[i]; } return sum / size;} void main() ... { __int16 array[] = ...{20000,10000,15000}; __int16 val = ::average(array,0,3); cout<<"平均值="<<val<<endl;} template < class T, int size > class stack ... {private: T size[100];public: void push(T); T pop();} ;template < class T, int size > void stack < T,size > ::push(T ch) ... { cout<<"in the push area"<<endl;} template < class T, int size > T stack < T,size > ::pop() ... { T a = 0; return a;} void main() ... { stack<int,100> a; a.pop(); a.push(100);}