C程序设计(六)_第1页
C程序设计(六)_第2页
C程序设计(六)_第3页
C程序设计(六)_第4页
C程序设计(六)_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、C+程序设计(六)常宝宝北京大学计算机科学与技术系模板为什么需要模板?在C+中引入模板最主要的目标仍然是为了使代码具有好的可重用特性。在C+中,妨碍代码重用的原因之一在于函数以及类都和类型有很强的关联性,如果一个函数在定义时只能处理整型类型的输入参数,则该函数就不能处理字符型或其它程序员自定义的类型。类也具有相同的问题,类中的数据成员往往也具有确定的类型。模板的引入正是为了解决在这种情形下的代码重用问题。在C+中有两类模板函数模板类模板函数模板先看一个例子(交换两个变量的内容)。swap(int&, int& b)只能交换两个整型变量的内容,不能交换两个double型的变量或两个student

2、类型的对象的内容。如:int ix = 6, iy = 7;swap(ix, iy);double dx =6.5, dy=7.5;swap(dx, dy);/错误,类型不匹配student sx(“王二”,“10023009”, 98 ),sy(“陈清扬”,“10023010”, 63 );swap(sx, sy); /错误,类型不匹配void swap(int& a , int& b) int temp = a; a = b; b = temp;函数模板C+中提供了函数重载的能力,可以用重载的办法定义能处理其它类型的函数。重载提供了函数的另外一种定义,但不是代码重用,程序员仍须复制原有函数

3、的函数定义,并在原有函数定义的基础上进行修改,在修改过程中,又有可能引入错误。void swap(double& a , double& b) double temp = a; a = b; b = temp;void swap(student& a , student& b) student temp = a; a = b; b = temp;函数模板在C+中,可以通过定义函数模板的方式解决因类型不同而导致的代码不能重用的问题。在函数模板中,类型本身可被定义成模板参数,C+编译器根据函数调用时提供的参数的参数类型自动生成处理不同类型的正确函数。通过函数模板定义的函数不是一个函数,而是一组函数

4、。定义函数模板使用保留字template,定义格式如下:template 返回类型 函数名( 函数型式参数表 ) . 函数模板模板参数表中的参数可以有多个,多个参数间用逗号间隔。模板参数通常代表一个类型(模板类型参数,注意和函数参数不同),模板类型参数形式如下:class 类型参数名 (或 typename 类型参数名)在模板函数的函数定义中,可以使用模板参数表中的类型参数,就象使用一个基本数据类型或用户已定义好的类型一样。template void swap(T& a , T& b) T temp = a; a = b; b = temp;函数模板在完成模板函数定义后,可以象调用一般函数那样

5、调用模板函数。int ix = 6, iy = 7;swap(ix, iy);C+ 编译器在遇到调用用模板方式定义的函数时,会根据调用函数的参数类型构造出一个个具体的函数。这个过程称为函数模板的例化(instaniation)。void swap(int& a , int& b) int temp = a; a = b; b = temp;T = intvoid swap(double& a , double& b) double temp = a; a = b; b = temp;T = double函数模板在调用函数模板时,C+编译器通常是根据函数实参的类型来例化函数模板,这个过程由C+编

6、译器自动进行,称为模板参数推导(template argument deduction)。程序员在调用模板函数时也可显式指定用以替换模板类型参数的模板实参,这样,C+编译器无需进行模板参数推导即可对函数模板进行例化。此时,模板函数的调用形式如下:模板函数名 (函数实参表);如:float fx = 6.5 , fy = 7.5;swap(fx, fy);指定的模板实参应和函数实参类型匹配。如:int ix = 6, iy = 7;swap(ix, iy);/错误函数模板若程序员不提供模板实参,C+编译器自动进行模板参数推导,有时候,作为函数返回类型的模板参数不能被推导出来。此时,需要显式指明模

7、板实参。程序员可以仅提供部分模板实参,其余的模板实参仍由编译器自动推导。且省略掉的实参必须是模板参数表尾部的参数对应的实参。template T1 sum( T2 a, T3 b) return a + b;.int x = 6; float y = 9.9, sigma;sigma = sum(x, y);/错误sigma = sum(x,y);/正确sigma = sum(x,y);/正确sigma = sum(x,y);/错误函数模板有时候,定义的模板函数并不能适合任何一种数据类型,对这些数据类型例化得到函数可能包含错误。因为模板函数总是考虑到尽可能多的数据类型,因此对某一种具体数据类型

8、而言,模板例化得到函数效率可能不高。template T max(T t1, T t2) return (t1t2?t1:t2);.char* szx=“World”, *szy=“Hello”, *szmax;szmax = max(szx, szy);/结果是什么?/ szmax = “Hello”char* max(char* t1, char* t2) return (t1t2?t1:t2);T = char*函数模板当函数模板不适于某类数据类型时,此时可以通过特化的方式为该数据类型提供合适的函数定义,形式如下:template返回类型 函数名(函数形参表) .在进行函数模板特化时,保

9、留字template、后面的不可缺少,函数名后的模板实参在编译器能够成功推导的情况下可以省略。template char* max(char* t1, char* t2) return ( strcmp(t1, t2) 0 ? t1 : t2);类模板和函数一样,类同样具有类型依赖性。在定义类的时侯,类中的数据成员、成员函数的返回值以及参数都必须有确定的类型,有时候这也会妨碍类代码的可重用性。问题定义动态数组元素个数应可动态变化元素类型应没有限制例子: Stash.h Stash.cpp StashTest.cppclass Stash int quantity; int next; int*

10、 storage; void inflate(int increase);public: Stash(); Stash(int initQuantity); Stash(); int add(int& element); int& fetch(int index) const; int& operator(int index) const; int count() const;类模板为了解决类依赖类型的问题,可以使用类模板,类模板的定义和函数模板的定义类似,使用保留字template,格式如下:templateclass 类名 ;模板参数表中的参数可以有多个,多个参数间用逗号间隔。模板参数通常

11、代表一个类型,模板类型参数形式如下:class 类型参数名 (或 typename 类型参数名)类模板同函数模板一样,一个类模板实际上对应了一组类。当定义一个模板类的对象时,程序员需要提供模板实参,C+编译器根据程序员提供的模板实参生成一个个具体的适合不同类型的类定义,形式如下:类名 对象名.Stash intStash;Stash floatStash;Templateclass Stash int quantity; int next; T* storage; void inflate(int increase);public: Stash(); Stash(int initQuantit

12、y); Stash(); int add(T& element); T& fetch(int index) const; T& operator(int index) const; int count() const;class Stash int quantity; int next; int* storage; void inflate(int increase);public: Stash(); Stash(int initQuantity); Stash(); int add(int& element); int& fetch(int index) const; int& operat

13、or(int index) const; int count() const;StashT=int类模板C+编译器根据模板实参生成类的过程被称为类模板例化。class Stash int quantity; int next; student* storage; void inflate(int increase);public: Stash(); Stash(int initQuantity); Stash(); int add(student& element); student& fetch(int index) const; student& operator(int index) c

14、onst; int count() const;StashT=student类模板模板参数可以分成两类 类型参数:值是类型 非类型参数:值是常量有时候,类中需要一个常量,此时使用非类型参数,非类型参数形式如下:类型 参数名.templateclass Stash .;如果模板参数表中含有非类型参数,定义对象时,程序员需要提供作为实参的常量值。这相当于在程序中定义了一个常量,如:Stash intStash;/等同于const int inc = 50 类模板对于非类型参数,可以有默认值(旧标准)。如:template class Stash .;同函数默认值一样,默认值的指定必须按照从右向左的

15、顺序进行。template /正确template /正确template /错误 如果指定了默认值,定义对象时,如果程序员没有提供模板实参,则表示使用默认值。如:stash intStash; /等同于 stash intStash;类模板例化后的模板类和普通类一样可以出现在普通类可以出现的任何地方,如:void f1(Stash & a) . Stash& f2( int a) .Stash* pIntStash = new Stash;类模板类模板的成员函数可以在类内定义,也可以在类外定义。在类内定义比较简单,和普通类在类内定义成员函数基本相同,不同之处在于其中可能出现模板参数。在类外定

16、义模板类的成员函数要使用不同的语法,成员函数前必须加上保留字template及模板参数。且第一次出现类名的时侯也应有模板参数表,但此时只列参数名。形式如下:template 返回类型 类名:成员函数名(函数形参表) .Templateclass Stash . public: . T& fetch(int index) const; assert(index = 0 ); assert(index next ); return storageindex; .;template Stash:Stash() : quantity(0),next(0), storage(0) template Stash:Stash() if(storage != 0) delete storage;template int Stash:add(T& element) if(next = quantity) inflate(increment); storagenext = element; next+; return(next - 1);类模板类模

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论