290 likes | 490 Views
第 1 章 C++ 程序设计基础. 网络游戏开发 -C++ 程序设计. 第 9 章 模板与 STL. 函数模板 类模板. 模板的概念. 类模板的定义和使用 类模板中的静态成员和友元 类模板中的特例版本. 理解模板技术 掌握函数模板的使用 掌握类模板的使用. 第 9 章 模板与 STL. 9.1 模板. 模板( templates ) 针对“一个或多个尚未明确的数据类型(包括类类型)”所设计的函数或类。 在不确定要操作数据的类型的情况下就实现操作方法。 模板是在函数和类的基础上提供了更高一层的抽象。. 第 9 章 模板与 STL. 9.1 模板.
E N D
第1章 C++程序设计基础 网络游戏开发-C++程序设计
第9章 模板与STL 函数模板 类模板 模板的概念 类模板的定义和使用 类模板中的静态成员和友元 类模板中的特例版本 理解模板技术 掌握函数模板的使用 掌握类模板的使用
第9章 模板与STL 9.1 模板 模板(templates) • 针对“一个或多个尚未明确的数据类型(包括类类型)”所设计的函数或类。 • 在不确定要操作数据的类型的情况下就实现操作方法。 • 模板是在函数和类的基础上提供了更高一层的抽象。
第9章 模板与STL 9.1 模板 9.1.1 函数模板 1.函数模板的概念 利用函数模板(带类型参数的函数),一次定义出具有共性的一组函数。 • 除类型参数外 • 函数名相同,参数个数相同 • 返回类型可以不同 • 处理多种不同类型数据的函数
第9章 模板与STL 9.1 模板 9.1.1 函数模板 1.函数模板的概念 重载函数 函数模板 int max (int a, int b) { //函数max,求两个int 型数据的最大值 if(a>b) return a; else return b; } double max (double a, double b) { //重载函数max,求两个double 型数据的最大值 if(a>b) return a; else return b; } … template <class T> T max (T a, T b) { if(a>b) return a; else return b; }
第9章 模板与STL 9.1 模板 9.1.1 函数模板 2.函数模板的说明 返回类型 函数名(参数表){函数体}; template <模板参数表> 函数定义; template:关键字。指明为函数模板或类模板。 模板参数表:用尖括号括起来,一个或多个模板参数,用“,”分开。 模板参数:其格式为class<类名>,其中的类名是一个标识符,该类名对应的实参类型可以是任何类型。
第9章 模板与STL 9.1 模板 9.1.1 函数模板 2.函数模板的说明 函数模板在被调用时与同名的函数调用没有什么区别 函数调用过程: 1)首先搜索程序说明中是否有参数表恰与max(c1,c2)之参数表完全相同的同名函数,如果有,就调用此函数代码付诸执行。否则执行下一步; 2)检查是否有函数模板,经适当实例化成为参数匹配的同名函数。如果有,调用此实例化的模板函数代码付诸执行。否则执行下一步;
第9章 模板与STL 9.1 模板 9.1.1 函数模板 2.函数模板的说明 3)检查是否有同名函数,可经参数的自动转换后实现参数匹配。如果有,调用该函数代码付诸执行; 4)如果三种情况都未找到匹配函数,则按出错处理; 5)值得注意的是,模板函数调用时,与一般函数不同之处在于,它不允许类型的转换。 模板函数也可以重载。同样,重载的条件是二同名模板函数必须有不同的参数表。
第9章 模板与STL 9.1 模板 9.1.1 函数模板 3.函数模板应用举例 #include <iostream> using namespace std; //第一个函数模板sum,使用了一个类型参数Type,具有两个形参 //本函数模板sum 的功能为:求出array 数组的前size 个元素之和并返回 template <class Type> Type sum (Type * array, int size ) { Type total=0; for (int i=0;i<size;i++) //累加前size 个数到total total+=*(array+i); return total; }
第9章 模板与STL 9.1 模板 9.1.1 函数模板 3.函数模板应用举例 //功能:求出a1 数组与a2 数组的前size 个元素之和并返回 template <class Type> Type sum (Type * a1, Type * a2, int size ) { Type total=0; for (int i=0;i<size;i++) //累加a1 数组与a2 数组的前size 个数到total total+=a1[i]+a2[i]; return total; } void main() { int a1[10]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int a2[8]={2, 4, 6, 8, 10, 12, 14, 16}; double af[10]={1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 11}; cout<<sum(a1,10)<<endl; //求出a1 数组前10 个元素之和并输出 cout<<sum(af,10)<<endl; //求出af 数组前10 个元素之和并输出 cout<<sum(a1,a2,8)<<endl; //求出a1 数组与a2 数组的前8 个元素之和并输出 }
第9章 模板与STL 9.1 模板 9.1.2 类模板 1. 类模板的说明 template <模板参数表> class 类模板名 {类模板定义体}; template:关键字,指明本说明为类模板说明或函数模板说明。 模板参数表:用尖括号< ,>括起来,用来说明若干个类型形参或普通形参。
第9章 模板与STL 9.1 模板 9.1.2 类模板 1. 类模板的说明 • 模板参数表 • 类型形参 • 普通形参 class 类型形参名 类型 普通形参名 注意函数模板不许使用普通形参!
第9章 模板与STL 9.1 模板 9.1.2 类模板 1. 类模板的说明 template <class T, int i> class TestClass { //具有类型形参T 与普通形参i 的类模板TestClass T buffer[i]; //T 类型的数组buffer,数组大小随普通形参i 的大小而变化 ... }
第9章 模板与STL 9.1 模板 9.1.2 类模板 2. 类模板的使用 #include <iostream> using namespace std; template <class keytype> class Queue { //类模板Queue,使用类型形参keytype int Maxsize; //队列的大小 int front,rear; //元素放在queue[front+1]到queue[rear]之中 keytype *queue; //动态数组queue,用来存放队列数据 public: … Queue<int> Qi(10); //以int取代类型形参keytype后成为一个具体类 Queue<double> Qf1(10),Qf2(10);
第9章 模板与STL 9.1 模板 9.1.2 类模板 2. 类模板的使用 利用类模板(带类型参数或普通参数的类): • 一次定义具有共性的一组类。 • 所定义类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值都可以是任意类型的 • 将程序所处理对象(数据)的类型参数化 • 提高了程序的抽象层次与可重用性
第9章 模板与STL 9.1 模板 9.1.2 类模板 3. 使用类模板时要注意的几个问题 不能使用类模板来直接生成对象,故须首先对模板参数指定“实参” TestClass<char, 10> objA; //以char 取代类型形参T 并以10 取代普通形参i 后形成的具体类 TestClass<double, 8> objB; //以double 取代类型形参T 并以8 取代普通形参i 后形成的具体类 也可以用由用户定义的类(类型)来进行实例化。 TestClass <complex,15> complexArray; TestClass <point,20> points;
第9章 模板与STL 9.1 模板 9.1.2 类模板 3. 使用类模板时要注意的几个问题 • 类模板成员函数的说明 类体外定义类模板的成员函数,其定义格式类似于函数模板。 template <模板参数表> 函数类型 类模板名 <模板参数名字表>::成员函数名 ( 函数参数表 ) { ... //成员函数的函数体 }; template <class T, int i> T TestClass<T,i>:: getData(int j) { ... //成员函数的函数体 };
第9章 模板与STL 9.1 模板 9.1.2 类模板 3. 使用类模板时要注意的几个问题 • 类模板的参数 类模板是对于类的进一步抽象,被称为类属类,可以说是类的类。 • 模板的定义体现了这个集合中的类的共性; • 模板参数则标识出集合中类的区别。
第9章 模板与STL 9.1 模板 9.1.2 类模板 4. 使用类型参数和普通参数的类模板 #include <iostream> using namespace std; template <class T, int i> class TestClass { //类模板TestClass,使用类型形参T 以及普通形参i public: T buffer[i]; //T 类型的buffer 数组,数组大小由普通形参i 的值指定 T getData(int j); //getData 函数,负责返回T 类型的buffer(数组) //的第j 个分量 }; template <class T, int i>T TestClass<T,i>::getData(int j) { //在类体外定义成员函数getData return *(buffer+j); //返回buffer(数组)的第j 个分量 };
第9章 模板与STL 9.1 模板 9.1.3 关于类模板的若干问题说明 1.类模板的静态成员 类模板也允许有静态成员。 它们是类模板之实例化类的静态成员,而不属于类模板。 aiobj1 aiobj1.t aiobj2 aiobj1.t CA<int> static int t; template<class T>class C { static T t; //静态成员t }; CA<int>aiobj1, aiobj2; CA<char>acobj1, acobj2; acobj1 acobj1.t CA<char> static char t; acobj2 acobj2.t
第9章 模板与STL 9.1 模板 9.1.3 关于类模板的若干问题说明 2.类模板的友元 它将是该类模板的所有实例化类的友元函数; 1)友元函数为一般函数 2)友元函数为一函数模板,但其类型参数与类模板的类型参数无关。 3)更复杂的情形是,该友元函数为一函数模板,且它与类模板的类型参数有关。 该函数模板的所有实例化(函数)都是类模板的所有实例化类的友元; 可能只是该类模板的某些特定实例化(而不是所有实例化)类的友元。
第9章 模板与STL 9.1 模板 9.1.3 关于类模板的若干问题说明 3.特例版本 类模板的使用十分方便,但大多数类模板不能任意进行实例化。 C++语言中没有对模板的“实参”类型进行检查的机制, 仅仅是通过实际操作中发生语法错误时,才能指出实例化的错误。 以下案例,如采用用户定义类型而又未在该类中对运算符“<<”进行重载时,就会产生问题: template <class T> class stack { //栈中元素类型为T 的stack 类模板 T num [MAX]; //num 中存放栈的实际数据 int top; //top 为栈顶位置 public: stack () { top=0; } //构造函数 void push (T a) { num[top++]=a; } //将数据a"压入"栈顶 void showtop(){if(top>1) cout<<"Top_Member:"<<num[top-1]<<endl;}; };
第9章 模板与STL 9.1 模板 9.1.3 关于类模板的若干问题说明 4. 按不同方法来派生类模板 1)一般类(其中不使用类型参数的类)作基类,派生出类模板(其中要使用类型参数)。 template <class T> class CA:public CB { //被派生出的CA 为类模板,使用了类型参数T,其基类CB 为一般类 T t; //私有数据为T 类型的 public: ... };
第9章 模板与STL 9.1 模板 9.1.3 关于类模板的若干问题说明 4. 按不同方法来派生类模板 2)类模板作基类,派生出新的类模板。但仅基类中用到类型参数T(而派生的类模板中不使用T)。 template <class T> class CA:public CB<T> { //CA 为类模板,其基类CB 也为类模板。注意,类型参数T //将被“传递”给基类CB,本派生类中并不使用该类型参数T double t1; //私有数据成员 public: ... };
第9章 模板与STL 9.1 模板 9.1.3 关于类模板的若干问题说明 4. 按不同方法来派生类模板 3)类模板作基类,派生出新的类模板,且基类与派生类中均使用同一个类型参数T。 template <class T> class CA:public CB<T> { //CA 为类模板,其基类CB 也为类模板。注意,类型参数T 将被 //“传递”给基类CB;本派生类中也将使用这同一个类型参数T T t1; //数据为T 类型的 public: ... }; 4)类模板作基类,派生出新的类模板,但基类中使用类型参数T2,而派生类中使用另一个类型参数T1(而不使用T2)。
第9章 模板与STL 小结 本章主要讲解C++模板的基础知识 • 函数模板 • 类模板
第9章 模板与STL 自测题 1.模板只能用于基本数据类型。() 2.一般模板的设计受到重视是因为其通用性和可重用性强。() 3.函数模板可以像一般函数那样来直接使用,用户只需给出具体的实参。() 4.模板函数调用时,与一般函数相同,可以进行类型的转换。() 5.类模板是对于类的进一步抽象。()
第9章 模板与STL 自测题 1.模板只能用于基本数据类型。(x) 2.一般模板的设计受到重视是因为其通用性和可重用性强。(√ ) 3.函数模板可以像一般函数那样来直接使用,用户只需给出具体的实参。(X ) 4.模板函数调用时,与一般函数相同,可以进行类型的转换。(X ) 5.类模板是对于类的进一步抽象。( √ )
第9章 模板与STL 课后作业 【作业1】 .用模板实现一个链表类,可保存和操作所有的基础数据类型。 【作业2】 .编写一个对具有n 个元素的数组x[]求最大值的程序,要求将求最大值的函数设计成函数模板。 【作业3】 .编写一个使用类模板对数组进行排序、查找和求元素和的程序。