第8章 异常,模板_第1页
第8章 异常,模板_第2页
第8章 异常,模板_第3页
第8章 异常,模板_第4页
第8章 异常,模板_第5页
已阅读5页,还剩50页未读 继续免费阅读

下载本文档

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

文档简介

1第8章 异常(exception),

模板(template)

2主要内容异常模板函数模板类模板命名空间31.

异常(exception)4C++中错误被称为异常或例外(Exception)。异常是运行时产生的错误,是由大量的例外情况产生的,例如内存用尽,不能打开文件,使用不合适的值初始化对象…51.1 异常的引入C语言处理错误时,通常返回一个特殊的值,用此值来表示函数产生了一个错误。例如:

if(somefunc()==ERROR_RETURN_VALUE) //handletheerrororcallerror-handlerfunction else //proceednormally if(anotherfunc()==NULL) //handletheerrororcallerror-handlerfunction else //proceednormally if(thirdfunc()==0) //handletheerrororcallerror-handlerfunction else //proceednormally

6这种处理的问题是:每调用一次函数,程序就必须检查一遍返回值,代码量增多。当在程序中使用类库时,这个问题变得更加复杂。使得错误检测更加不容易。71.2 异常的语法C++使用try、throw和catch语句实现异常处理。当预测到某段程序将可能出现问题时,则将该段程序放在try语句之后,使该段程序得以有机会抛出异常。8在程序的某个函数中发现异常时使用throw表达式抛出这个异常,这个异常被抛给该函数的调用者。调用者用catch捕捉该异常并进行相应的处理。9C++库中的一些库函数已经设计了异常抛出。也就是系统会自动throw一些定义好的异常,以便C++程序里可以catch它们,并进行处理。例:badalloc.cpp10程序里自定义异常,并进行处理方法:#include<iostream.h>classBall{ intradius;public: Ball(intrad);voidprint()const{cout<<radius<<endl;}};11Ball::Ball(intrad){radius=rad;if(radius==0)throwrad;//如果有错误,使用 throw抛出一个标识

}12

intmain(){try//把可能出现异常的程序放在try复合语句中

{Ballmyball(1);Ballyourball(0);//exception}catch(int){//对应异常标识,给出相应处理方法

cout<<"exception:invalidradius,radiusmustbegreatthan0"<<endl;}return0;}13C++语言提供对处理异常情况的内部支持。

try{//try关键字引导的try块

……//可能引发错误的程序段

……throwlabel1//异常标识

……throwlabel2//异常标识}//结束try块14

catch(异常类型声明1)//catch块与label的类型匹配

{

……//处理响应异常

}

catch(异常类型声明2)//catch块与label的类型匹配{

……//处理响应异常}15抛掷异常与异常处理程序之间,是按数据类型的严格匹配来捕获的。下面是几个throw和catch对应的例子:“throw1;”和“throwi;”被catch(inti)

捕获“throwdnum”被catch(doublednum)

捕获“throw"abc";”被catch(char*ptr)

捕获“throwstring("abc");”被catch(stringstr)

捕获“throwpoint(1.2,5.8);”被catch(pointa)

捕获16演示异常的例子。#include<iostream>usingnamespacestd;doubleDiv(doublex,doubley);voidmain(){boolflag=true; try { cout<<Div(15.5,5.5)<<endl; 17cout<<Div(8.25,8.25)<<endl;cout<<Div(70,3.3)<<endl;}//endoftry catch(double) { cout<<"exceptofdevidingzero.\n"; flag=false; } if(flag==false)cout<<"Thereisanymistake."<<endl; elsecout<<"Thatisok.\n"; cout<<"Exit..."<<endl;}18doubleDiv(doublex,doubley){ doubletemp; temp=x,x=x+y,y=temp-y;if(y==0) throwy; returnx/y;}19程序在处理异常之后,继续执行catch后面的if语句,直到结束。输出结果如下:1.2963exceptofdevidingzero.Thereisanymistake.Exit...202.函数模板(FunctionTemplate)21模板的作用:一个函数或者类去处理不同的数据类型。使用模板可以使用户为类或者函数声明一种通用模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。模板概述222.1函数模板的引入假如编写一个函数,返回数的绝对值。对于int数据类型,此函数可写为:

intabs(intn){ return(n<0)?–n:n; }对于long数据类型,此函数可写为:

longabs(longn){ return(n<0)?–n:n; }对于float数据类型,此函数可写为:

floatabs(floatn){ return(n<0)?–n:n; }23上面每个函数中,函数体都是一样,只是参数类型和返回值类型不一样。如果只把这个函数写一遍,而让其处理不同的数据类型,这正是函数模板所实现的。24函数模板就是一系列相似函数的模型。这些函数的代码形式相同,只是所针对的参数和返回值的数据类型不同。25template<classT>Tfunc(Targ){…}一个函数模板intfunc(intarg){…}charfunc(chararg){…}floatfunc(floatarg){…}i1=func(i2);c1=func(c2);f1=func(f2);参数类型决定函数实例化262.2 函数模板的定义欲定义一函数为template函数,其格式如下:

template<classType>

//template定义部分Typefuncname(Type,Type…){}

//真正函数定义部分

关键字数据类型函数的参数行27见例:tempabs.cpp在程序中定义了可以处理多种数据类型的函数abs(): template<classT> Tabs(Tn) { return(n<0)?–n:n; }28函数模板定义的创新之处在于:函数所使用的参数,返回值用一个通用名字如Type(anyType,T…)替代了int,long,float

等特定的类型。29程序tempabs.cpp中,

cout<<“\nabs(”<<int<<“)=”<<abs(int1);当调用到函数abs(int1)时,编译器才知道所用类型是int,因而用int代替abs模板中的所有T,这就是函数模板的实例化。

30函数模板并不是真正的函数,只是一种产生多种函数的模式或者框架,并不使程序代码占用内存。312.3 多参数函数模板见例:tempfind.cpp此函数模板有三个参数,两个是模板参数,一个是基本类型。此函数模板的作用是从数组中寻找特定的值,如果找到这个值,就返回所在位置,如果没有找到,则返回-1。参数分别为指向数组的指针,要找的特定值和数组大小。32332.4 多种类型模板参数在模板函数中可以使用多种类型模板参数。其函数定义的格式如下:

template<classType1,classType2> Type1fun(Type1a,Type2b){…}Type1,Type2为不同数据类型,返回值可以为Type1,Type2或其他基本类型。34注意:在定义类型参数时,每一类型参数都必须跟着一个关键字class,以下的格式是错误的:

Template<classType1,Type2>

//error!!而对于函数参数表中,每一个已定义的类型参数都必须至少被使用一次。以下的格式是错误的:

template<classT1,classT2,classT3> T3fun(T1a,T1b,T2c){..}

//error!!35修改程序tempfind.cpp,定义数组大小的类型名为btype:

template<classatype,classbtype> btypefind(atype*arrary,atypevalue,btypesize) { for(btypej=0;j<size;j++) { if(arrary[j]==value) returnj; return-1; }这样就可以使用int或者long类型作为数组大小。363. 类模板37模板的概念可以扩展到类。用一种类似函数模板的机制来解决类数据成员更改的问题——类模板。3.1 类模板的引入38例如:如下的stack类仅能存储int类型

classStack{ private: intst[MAX];//arrayofints inttop;//indexnumberoftopofstack

public: Stack(); voidpush(intvar);//takesintasarg.

intpop();//returnsintvalue };39如果想在栈中存储long类,则需要重新定义类:

classLongStack{ private: longst[MAX];//arrayoflongs inttop;//indexnumberoftopofstack

public: LongStack(); voidpush(longvar);//takeslongasarg.

longpop();//returnslongvalue };40如此一来,就需要为存储的每种数据类型定义新的Stack类。如使用类模板就方便得多。类模板的格式如下:

template<classType> classStack { //dataandmemberfunctionsusingargumenttype };3.2 类模板的定义41见例:tempstack.cpp此例中,模板参数是Type,此参数出现在类定义中涉及到数组st类型的所有地方。与函数模板相同,类模板只有使用的时候才被具体化为某一种类型。42类模板和函数模板的不同之处在于:函数模板的使用是由编译器自动决定的;而类模板定义对象时其真正类型必须由程序设计者自己指明。43例如:

Stack<float>s1;

此语句创建了对象s1,为s1的数据在内存中提供了空间;用float代替类定义中所有模板参数,同时也为成员函数提供内存空间。 如果创建其他类型的堆栈,如:

Stak<long>s2;

则为数据创建了不同的内存空间。44template<classT>classAclass{//statements….};源代码中的一个类模板obj1storesfloatsobj2storeintsobj3storeintsobj4storescharsobj5storescharsAclass<float>obj1;Aclass<int>obj3;Aclass<int>obj2;Aclass<char>obj5;Aclass<char>obj4;内存中不同类的多个对象453. 命名空间46为什么需要命名空间?命名空间是C++中的一个不常用的概念。C++中采用的是单一的全局变量命名空间。在这单一的空间中,如果有两个变量或函数的名字完全相同,就会出现冲突。47stringnamestringnamenamespacemynamespaceyour48命名空间定义名字空间的定义与一个类的定义非常相似:

namespaceMyLib{ //Declarations }在namespace定义的结尾,不必要跟一个分号。49namespace与class、structure、union和enum有着明显的区别:

1)namespace只能在全局范畴定义,但它 们之间可以互相嵌套。

2)一个namespace可以在多个头文件中。

3)不能像类那样去创建一个命名空间的实例。50使用命名空间

1.域名 命名空间中的任何命名都可以用域名明确指定,就像引用一个类名一样。51//两个在不同命名空间中定义的名字相同的变量namespacemyown1{

stringuser_name="myown1";}namespacemyown2{

stringuser_name="myown2";}52intmain(){

cou

温馨提示

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

评论

0/150

提交评论