C++STL泛型编程.ppt
《C++STL泛型编程.ppt》由会员分享,可在线阅读,更多相关《C++STL泛型编程.ppt(142页珍藏版)》请在三一文库上搜索。
1、1,C+STL泛型编程 (Generic Programming),2,为什么要采用泛型编程?,项目中,需要用到数组、链表、字符串、栈、队列、平衡二叉树等数据结构,以及排序、搜索等算法; 若全部自行编写比较麻烦; ANSI C+中包含了C+ STL (Standard Template Library , 标准模板库,又称C+泛型库),定义了常用的数据结构和算法,使用十分方便。 有了STL,不必再从头写大多的标准数据结构和算法,并且可获得非常高的性能。,但这不意味着我们不需要掌握基本数据结构与算法;相反,只有透彻理解了,才能更好的使用泛型!,泛型程序设计,由Alexander Stepanov
2、和David Musser创立,于1998年被添加进C+标准. 含义:编写不依赖于具体数据类型的程序. 目标:将程序写得尽可能通用 . 将算法从特定的数据结构中抽象出来,成为通用的. C+的模板为泛型程序设计奠定了关键的基础. STL (标准模板库, Standard Template Library)是泛型程序设计的一个范例.,代码重用(reuse)!,4,函数模板 模板函数的重载 类模板 堆栈类 继承 static成员 友元,模板,函数模板简介,5,【引例】交换2个整数和交换2个浮点数的C+程序:,/交换2个整数 void Swap(int ,int main() int a = 10,
3、b=20; float c = 1.2, d=2.4; cout “ a= “ a “ b= “ b; cout “ c= “ c “ d= “ c; Swap(a,b); cout “ a= “ a “ b= “ b; Swap(c,d); cout “ c= “ c “ d= “ c; return 0; ,两个Swap函数实现的功能相同,只是参数类型不同,但为了实现不同类型的数据交换必须分别编写函数。造成了重复劳动。,函数重载,6,能否提供一种方法将两个函数合并,以节省开发成本?,引例,typedef int DataType; void Swap(DataType ,当需要交换两个浮点
4、数时可以将DataType 定义成float 型数据即可。 typedef float DateType;,存在问题: 更改一种数据类型时,需要修改程序源代码,必须重新编译程序。 如果程序中需要交换多种数据类型数据, 怎么办?,7,引例,#include using namespace std; template void Swap (T ,模板声明,定义函数模板,通用的Swap!,模板机制,模板的概念,模板是一种使用无类型参数来产生一系列函数或类的机制。 模板是以一种完全通用的方法来设计函数或类而不必预先说明将被使用的每个对象的类型。 通过模板可以产生类或函数的集合,使它们操作不同的数据类型
5、,从而避免需要为每一种数据类型产生一个单独的类或函数。,8,模板分类,函数模板(function template) 是独立于类型的函数 可产生函数的特定版本 类模板(class template) 与类相关的模板,如vector 可产生类对特定类型的版本,如vector,9,模板工作方式,模板只是说明,需要实例化后才能执行或使用.,10,函数模板(function template),定义格式: template 类型名 函数名(参数表) 函数体 ,template void Swap (T ,11,template: 函数模板定义关键字. 中是函数的模板参数,参数可有一个或多个,逗号隔开。
6、不能为空! 模板参数常用形式: class 标识符 或者 typename 标识符 模板参数表明函数可以接收的类型参数,可以是内部类型,也可以是自定义类型.,【例1】简单函数模板定义和应用.,#include using namespace std; template T Max ( T a , T b ) return a b ? a : b ; int main ( ) cout “ Max ( 3 , 5 ) is “ Max ( 3 , 5 ) endl ; cout “ Max ( y , e ) is “ Max ( y , e ) endl ; cout “ Max ( 9.3
7、, 0.5 ) is “ Max ( 9.3 , 0.5 ) endl ; return 0; ,函数模板,int Max ( int a , int b ) return a b ? a : b ; ,由实参类型实例化,char Max ( char a , char b ) return a b ? a : b ; ,double Max ( double a , double b ) return a b ? a : b ; ,编译器生成的 模板函数,函数模板实例化,运行结果: Max(3,5) is 5 Max(y, e) is y Max(9.3, 0.5) is 9.3,函数模板的
8、原理分析: 函数模板中声明了类型参数T,表示了一种抽象类型. 编译器检测到程序调用函数模板Max时,用其第一个实参类型替换掉模板中的T,同时建立一个完整的函数Max,并编译该新建的函数. 本例中,针对三种数据类型,生成了三种函数.,【练习1】编写一个对具有n个元素的数组a 求最小值的程序,要求将求最小值的函数设计成函数模板。,#include using namespace std; template T MinArray(T a,int n) int i; T mina=a0; for( i = 1;i ai) mina=ai; return mina; ,void main() int a
9、rr1=1,3,0,2,7,6,4,5,2; double arr2=1.2,-3.4,6.8,9,8; cout“arr1数组的最小值为:“ MinArray(arr1,9) endl; cout“arr2数组的最小值为:“ MinArray(arr2,4)endl; ,运行结果: arr1数组的最小值为:0 Arr2数组的最小值为: -3.4,注意点1:实参类型与形参类型必须严格匹配.,#include using namespace std; template T Max ( T a , T b ) return a b ? a : b ; int main ( ) int a=3; f
10、loat b=1.5; cout “ Max (a,b) is “ Max(a,b) endl ; return 0; ,错误!模板类型不能提供类型的隐式转换,注意点2:在函数模板中允许使用多个类型参数。在template定义部分的每个模板形参前必须有关键字class或typename.,#include using namespace std; template void myfunc(T1 x , T2 y) coutx“, “yendl; ,运行结果: 100, hao 3.14, 10,void main() myfunc(100, “hao“); myfunc(3.14, 10L);
11、 ,注意点3:在template语句与函数模板定义语句之间不允许有别的语句。 Template int i; T Max(T x,T y) return(xy)? x : y;,8,/错误,不允许有别的语句,模板优缺点,优点: 函数模板方法克服了C语言用大量不同函数名表示相似功能的弊端; 克服了宏定义不能进行参数类型检查的弊端; 克服了C+函数重载用相同函数名字重写几个函数的繁琐. 缺点: 调试比较困难. 一般先写一个特殊版本的函数 运行正确后,改成模板函数,17,18,【练习2】编写一个函数模板,它返回两个值中的较小者,同时要求能正确处理字符串。 分析: 由于C+字符串比较的方法与字符型、数
12、值型都不同,因此函数模板不适用于字符串比较; 这里设计一个函数模板template T min(T a,T b),可以处理int、float和char 等数据类型; 为了能正确处理字符串,添加一个重载函数专门处理字符串比较,即char *min(char *a,char *b)。,#include #include template T min(T a, T b) return (ab?a:b); char *min(char *a,char *b) return (strcmp(a,b)0?a:b); void main() double a=3.14, b=8.28; char s1=“B
13、ad“,s2=“Good“; cout“输出结果:“endl; coutmin(a,b)endl; coutmin(s1,s2)endl; ,函数模板,函数重载,运行结果: 3.14 Bad,20,可以显式指定(explicitly specify),如: i=max(ia,5); d=max(da,6);,用函数模板求数组元素中最大值 template Groap max(const Groap *r_array,int size) int i; Groap max_val=r_array0; for ( i=1; i max_val ) max_val=r_arrayi; return m
14、ax_val; ,可读性更好。,21,函数模板可以重载, 形参表不同即可 例, 下面两个模板可以同时存在: template void print(T1 arg1, T2 arg2) cout void print(T arg1, T arg2) cout arg1 “ “ arg2endl; ,重载,22,例: 函数模板调用顺序,23,double Max(double a, double b) cout “MyMax“ endl; return 0; ,template T Max( T a, T b ) cout “Template Max 1“ endl; return 0; ,tem
15、plate T Max( T a, T2 b ) cout “Template Max 2“ endl; return 0; ,24,void main() int i=4, j=5; Max( 1.2, 3.4 ); Max( i, j ); Max(1.2, 3); ,25,匹配顺序 C+编译器遵循以下优先顺序: Step 1: 先找参数完全匹配的普通函数(非由模板实例化而得的函数) Step 2: 再找参数完全匹配的模板函数 Step 3: 再找实参经过自动类型转换后能够匹配的普通函数 Step 4: 上面的都找不到, 则报错,26,void main() int i=4, j=5; M
16、ax( 1.2, 3.4 ); Max( i, j ); Max(1.2, 3); ,/调用Max(double, double)函数,/调用第一个T Max(T a, T b)模板生成的函数,/调用第二个T Max(T a, T2 b)模板生成的函数,运行结果: MyMax Template Max 1 Template Max 2,27,可以在函数模板中使用多个类型参数, 可以避免二义性 template T1 myFunction( T1 arg1, T2 arg2) coutarg1“ ”arg2“n”; return arg1; myFunction( 5, 7 ); myFunct
17、ion( 5.8, 8.4 ); myFunction( 5, 8.4 );,/ok:replace T1 and T2 with int,/ok: replace T1 and T2 with double,/ok: replace T1 with int, T2 with double,28,类模板的定义,C+的类模板的写法如下: template class 类模板名 成员函数和成员变量 ; 类型参数表的写法就是: class 类型参数1, class 类型参数2, ,29,类模板里的成员函数, 如在类模板外面定义时, template 返回值类型 类模板名:成员函数名(参数表) ,类模
18、板的定义,30,用类模板定义对象的写法如下: 类模板名 对象名(构造函数实际参数表); 如果类模板有无参构造函数, 那么也可以只写: 类模板名 对象名;,类模板的定义,31,Pair类模板: template class Pair public: T1 key; /关键字 T2 value; /值 Pair(T1 k,T2 v) : key(k), value(v) ; bool operator ,类模板的定义,32,#include #include using namespace std; 。 void main() Pair stu(“Tom“, 19); Pair stu2(“Jac
19、k“, 20); if (stu.operator(stu2) ) cout stu.key “ “ stu.value; else cout stu.key “ “ stu2.value; ,运行结果: Jack 20,Pair类模板的使用:,33,使用类模板声明对象 编译器由类模板生成类的过程叫类模板的实例化 编译器自动用具体的数据类型替换类模板中的类型参数, 生成模板类的代码 由类模板实例化得到的类叫模板类 为类型参数指定的数据类型不同, 得到的模板类不同,同一个类模板的两个模板类是不兼容的 Pair * p; Pair a; p = /wrong,34,#include using n
20、amespace std; template class A public: template void Func(T2 t) cout a; a.Func(K); ,若函数模板改为 template void Func(T t)coutt 将报错 “declaration of class T shadows template parm class T ”,程序输出: K,/成员函数模板,/成员函数模板 Func被实例化,函数模版作为类模板成员,35,template class A public: template void Func(T2 t); ; template template
21、void A:Func(T2 t) cout t; ,void main() A a; a.Func(K); ,36,类模板的参数声明中可以包括非类型参数 template 非类型参数: 用来说明类模板中的属性 类型参数: 用来说明类模板中的属性类型, 成员操作的参数类型和返回值类型,类模板与非类型参数,37,template class CArray T arraysize; public: void Print( ) for(int i = 0; i size; +i) cout array i endl; ;,类模板与非类型参数,CArray a2; CArray a3;,38,CArr
22、ay a2; CArray a3; 注意: CArray和CArray完全是两个类 这两个类的对象之间不能互相赋值,类模板与非类型参数,39,类模板派生出类模板 模板类 (即类模板中类型/非类型参数实例化后的类) 派生出类模板 普通类派生出类模板 模板类派生出普通类,类模板与继承,派生,类模板,类模板,模板类,类模板,类模板,类模板,普通类,模板类,40,类模板从类模板派生,(1) template class A T1 v1; T2 v2; ; template class B : public A T1 v3; T2 v4; ;,template class C : public B T
23、v5; ;,void main() B obj1; C obj2; ,41,void main() B obj1; C obj2; ,class B:public A int v3; double v4; ; class A double v1; int v2; ;,42,类模板从模板类派生,template class A T1 v1; T2 v2; ; template class B:public A T v; ; int main() B obj1; return 0; 自动生成两个模板类:?,43,template class A T1 v1; T2 v2; ; template c
24、lass B:public A T v; ; int main() B obj1; return 0; 自动生成两个模板类: A和B,(2) 类模板从模板类派生,44,class A int v1; ; template class B : public A T v; ; int main() B obj1; return 0; ,(3) 类模板从普通类派生,45,(4)普通类从模板类派生,template class A T v1; int n; ; class B : public A double v; ; int main() B obj1; return 0; ,46,C+支持两种编
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- STL 编程
链接地址:https://www.31doc.com/p-3797167.html