第八章异常处理与模板 主要内容: ●异常处理概述:什么是异常以及异常处理的基本思想 异常处理基础:引发异常、捕获异常和异常处理的基本格式、异常类型及其匹配、再抛 ● 出异常、异常接口声明以及异常处理的执行过程。 ●异常处理中的构造与析构:抛出异常时的拷贝构造函数,在完全构造的对象与部分构造 的对象中抛出异常以及在析构函数中抛出异常。 模板的概念:模板的基本概念,模板的分类以及类模板、函数模板、模板类、模板函数 和对象之间的关系。 ●函数模板与模板函数:函数模板的定义格式、函数模板的实例化(模板函数),以及函 数模板和模板函数与一般函数的重载。 ● 类模板与模板类:类模板的定义格式以及类模板的实例化。 模板的特性:模板与继承的关系、模板与友元的关系以及模板与静态成员的关系。 选择 1模板是实现类属机制的一种工具,其功能非常强大,它既允许用户构造类属函数,即① ;也允许用户构造类属类,即②。 A模板函数 B函数模板 C模板类 D类模板 答案:①A ②C 注释:模板分为函数模板和类模板,它们分别允许用户构造模板函数和模板类。 2类模板的模板参数 A只可作为数据成员的类型 B只可作为成员函数的返回类型 C只可作为成员函数的参数类型 D以上三者都有 答案:D 注释:类模板使用户可以为类定义一种模式,使得类中的某些数据成员、某些成员函数的参 数和返回值可以取任意数据类型。 填空 1从一个模板函数产生的模板函数是同名的,因此编译器用重载的解决方法调用相应函数。 注释:同一函数模板实例化后的所有模板函数都必须执行相同的动作。 2函数模板的友元函数可以是模板函数或者非模板函数。 注释:函数模板的友元函数可以是如下形式: friend void fl(); friend void f2(X<T>&) >friend void A::f3(); friend void C<T>::f4(X<T>&); 3如果在类模板的定义中有一个静态数据成员,则在程序运行中会产生多个静态变量。 注释:类模板的每个实例,即每个模板类都会产生一个相应的静态数据成员变量,该模板类 的所有对象共享一个该类的静态数据成员
第八章 异常处理与模板 主要内容: z 异常处理概述:什么是异常以及异常处理的基本思想 z 异常处理基础:引发异常、捕获异常和异常处理的基本格式、异常类型及其匹配、再抛 出异常、异常接口声明以及异常处理的执行过程。 z 异常处理中的构造与析构:抛出异常时的拷贝构造函数,在完全构造的对象与部分构造 的对象中抛出异常以及在析构函数中抛出异常。 z 模板的概念:模板的基本概念,模板的分类以及类模板、函数模板、模板类、模板函数 和对象之间的关系。 z 函数模板与模板函数:函数模板的定义格式、函数模板的实例化(模板函数),以及函 数模板和模板函数与一般函数的重载。 z 类模板与模板类:类模板的定义格式以及类模板的实例化。 z 模板的特性:模板与继承的关系、模板与友元的关系以及 模板与静态成员的关系。 选择 1 模板是实现类属机制的一种工具,其功能非常强大,它既允许用户构造类属函数,即 ① ;也允许用户构造类属类,即 ② 。 A 模板函数 B 函数模板 C 模板类 D 类模板 答案:① A ②C 注释:模板分为函数模板和类模板,它们分别允许用户构造模板函数和模板类。 2 类模板的模板参数 。 A 只可作为数据成员的类型 B 只可作为成员函数的返回类型 C 只可作为成员函数的参数类型 D 以上三者都有 答案:D 注释:类模板使用户可以为类定义一种模式,使得类中的某些数据成员、某些成员函数的参 数和返回值可以取任意数据类型。 填空 1 从一个模板函数产生的模板函数是同名的,因此编译器用重载的解决方法调用相应函数。 注释:同一函数模板实例化后的所有模板函数都必须执行相同的动作。 2 函数模板的友元函数可以是模板函数或者非模板函数。 注释:函数模板的友元函数可以是如下形式: ¾ friend void f1(); ¾ friend void f2(X<T>&); ¾ friend void A::f3(); ¾ friend void C<T>::f4(X<T>&); 3 如果在类模板的定义中有一个静态数据成员,则在程序运行中会产生多个静态变量。 注释:类模板的每个实例,即每个模板类都会产生一个相应的静态数据成员变量,该模板类 的所有对象共享一个该类的静态数据成员。 1
阅读程序 写出运行结果 1 #include <iostream.h> int Div(ints,inty) { if(y=0) throw y; return x/y; void main() { try cout<<"7/3=<<Div(7,3)<<endl; cout<<9/0=”<<Div(9,0)<<endl, cout<<"8/4="<<Div(8,4)<<endl; } catch(int) { cout<<"Exception of dividing zero."<<endl; cout<<"It is OK."<<endl: } 答案: 713=2 Exception of dividing zero. It is OK. 注释:ty块中第一次函数调用执行正常,由于Div函数的返回类型为it类型,因此结果为 7/3=2。 第二次函数调用时,由于除数为O,因此Dⅳ函数抛出异常。此时函数的执行流程立即返回 到该子函数的调用者处,即主函数中的y块:y块捕获到异常后,程序的执行流程又立即 跳转到异常处理器,即catch块中。在catch块中按照异常类型进行匹配,达到结果Exception of dividing zero. 由于程序中出现了异常,因此在catch块处理程序被执行后,程序直接跳转到跟随在异常处 理之后的语句执行,得到结果It is OK 2 #include<iostream.h> template <class T> Tmax(Tx,Ty) { return (x>y?x:y); 2
阅读程序 写出运行结果 1 #include <iostream.h> int Div(int s,int y) { if(y==0) throw y; return x/y; } void main() { try { cout<<”7/3=”<<Div(7,3)<<endl; cout<<”9/0=”<<Div(9,0)<<endl; cout<<”8/4=”<<Div(8,4)<<endl; } catch(int) { cout<<”Exception of dividing zero.”<<endl; } cout<<”It is OK.”<<endl; } 答案: 7/3=2 Exception of dividing zero. It is OK. 注释:try 块中第一次函数调用执行正常,由于 Div 函数的返回类型为 int 类型,因此结果为 7/3=2。 第二次函数调用时,由于除数为 0,因此 Div 函数抛出异常。此时函数的执行流程立即返回 到该子函数的调用者处,即主函数中的 try 块;try 块捕获到异常后,程序的执行流程又立即 跳转到异常处理器,即 catch 块中。在 catch 块中按照异常类型进行匹配,达到结果 Exception of dividing zero. 由于程序中出现了异常,因此在 catch 块处理程序被执行后,程序直接跳转到跟随在异常处 理之后的语句执行,得到结果 It is OK. 2 #include<iostream.h> template <class T> T max ( T x, T y) { return (x>y?x:y); } 2
void main() cout<<max(2,5)<”,”<max(3.5,2.8)<endl; } 答案:5,3.5。 注释:说明函数模板的使用方法。ax()是一个函数模板,它返回两个参数中的较大者。 在调用时自动联编相应的max()函数。 3 #include<iostream.h> template <class T> class Sample { Tn; public: Sample(T i)(n=i;) void operator++(); void disp0{cout<<”n=”<<n<<endl;} 方 template <class T> void Sample<T>::operator ++( { n+=l: ∥不能用n++,因为double类型不能用++ void main() Sample<char>s('a'); s+; s.disp(), } 答案:n=b 注释:说明类模板的使用方法。Sample是一个类模板,由它产生模板类Sample<-char>,通 过构造函数给n赋值,通过重载++运算符使n增1,这里n由'a'增1变成b'。 程序设计 1编写一个程序,采用异常处理的方法,在指定的文件不存在时显示出错信息:文件存在时 显示其大小。 参考答案: 当文件流fle不存在时,则fle.fail()返回真,抛出一个字符串错误,在catch()中检测 该错误,输出出错信息。本题程序如下: include <iostream.h> include <fstream.h> void main ( 3
void main() { cout<<max(2,5)<<”,”<<max(3.5,2.8)<<endl; } 答案:5,3.5。 注释:说明函数模板的使用方法。max()是一个函数模板,它返回两个参数中的较大者。 在调用时自动联编相应的 max()函数。 3 #include<iostream.h> template <class T> class Sample { T n; public: Sample(T i) {n=i;} void operator++(); void disp() {cout<<”n=”<<n<<endl;} }; template <class T> void Sample<T>::operator ++() { n+=1; //不能用 n++,因为 double 类型不能用++ } void main() { Sample<char> s(‘a’); s++; s.disp(); } 答案:n=b 注释:说明类模板的使用方法。Sample 是一个类模板,由它产生模板类 Sample<char>,通 过构造函数给 n 赋值,通过重载++运算符使 n 增 1,这里 n 由’a’增 1 变成’b’。 程序设计 1 编写一个程序,采用异常处理的方法,在指定的文件不存在时显示出错信息;文件存在时 显示其大小。 参考答案: 当文件流 file 不存在时,则 file.fail()返回真,抛出一个字符串错误,在 catch()中检测 该错误,输出出错信息。本题程序如下: # include <iostream.h> # include <fstream.h> void main () 3
char fn[20]; cout<”文件名:”, cin>>fn: ifstream file(fn,ios:;nocreate(ios::in); try if(file.fail()) throw“error', } catch(char *s) { cout<<”不存在文件:”<<fn<<end: return; ; file.seekg(0,ios::end); cout<<fn<”文件大小:”<<file.tellg()<"Byte”<<endl; } 本程序执行结果: 文件名:abc.cpp 不存在文件abc.cpp 2编写一个函数模板,它返回两个值中的较小者,同时要求能正确处理字符串。 这里设计一个函数模板template<classT>Tmin(Ta,Tb),可以处理int,float和char等数据 类型,为了能正确处理字符串,添加一个重载函数专门处理字符串比较,即char*min(char *a,char*b)。本题程序如下: #include<iostream.h> #include<string.h> template <class T> T min(Ta,Tb) { return (a<b?a:b); } char *min(cha *a,char *b) return (strcmp(a,b)<0?a:b); } void main() { double a=3.56.b=8.23: char s1[0=”Hello'”,s20=”Good”, cout<输出结果:”<<endl; cout<<”“<<a<”,”<<b<<”中较小者:”<min(a,b)K<endl; cout<<”“<sl<<”,”<<s2<<”中较小者:”<<min(sl,s2)<endl; 4
{ char fn[20]; cout<<”文件名:”; cin>>fn; ifstream file (fn,ios:;nocreate(ios::in); try { if(file.fail()) throw “error”; } catch(char *s) { cout<<”不存在文件:”<<fn<<endl; return; }; file.seekg(0,ios::end); cout<<fn<<”文件大小:”<<file.tellg()<<”Byte”<<endl; } 本程序执行结果: 文件名:abc.cpp 不存在文件 abc.cpp 2 编写一个函数模板,它返回两个值中的较小者,同时要求能正确处理字符串。 这里设计一个函数模板 template<class T> T min(T a ,T b),可以处理 int,float 和 char 等数据 类型,为了能正确处理字符串,添加一个重载函数专门处理字符串比较,即 char *min( char *a, char *b)。本题程序如下: #include<iostream.h> #include<string.h> template <class T> T min (T a, T b) { return (a<b?a:b); } char *min(cha *a, char *b) { return (strcmp(a,b)<0?a:b); } void main() { double a=3.56,b=8.23; char s1[]=”Hello”,s2[]=”Good”; cout<<”输出结果:”<<endl; cout<<” “<<a<<”,”<<b<<”中较小者:”<<min(a,b)<<endl; cout<<” “<< s1<<”,”<<s2<<”中较小者:”<<min(s1,s2)<<endl; 4
程序执行结果: 输出结果: 3.56,8.23中较小者:3.56 Hello,Good中较小者:Good 3一个Sample类模板的私有数据成员为Tn,在该类模板中设计一个operator--=重载运算符 函数,用于比较各对象数据的n数据是否相等。 本题程序如下: #include <iostream.h> template <class T> class Sample { T public: Sample(T i)(n=i; int operator=(Sample &) 方 template <class T> int Sample<T>::operator-(Sample &s) { if(n==s.n) return 1; else return 0; } void main() Sample<int>s1(2).s2(3): cout<<”s1与s2的数据成员”<<(sl一s2?”相等”:”不相等")<endl, Sample<double>s3(2.5),s4(2.5); cout<<”s3与s4的数据成员”<(s3=s4?”相等”.”不相等)<<endl; 程序执行结果: s1与s2的数据成员不相等 s3与s4的数据成员相等 5
} 程序执行结果: 输出结果: 3.56,8.23 中较小者:3.56 Hello,Good 中较小者:Good 3 一个 Sample 类模板的私有数据成员为 T n,在该类模板中设计一个 operator==重载运算符 函数,用于比较各对象数据的 n 数据是否相等。 本题程序如下: #include <iostream.h> template <class T> class Sample { T n; public: Sample(T i) {n=i; } int operator==(Sample &); }; template <class T> int Sample<T>::operator==(Sample &s) { if(n==s.n) return 1; else return 0; } void main() { Sample<int> s1(2),s2(3); cout<<”s1 与 s2 的数据成员”<<(s1==s2?”相等”:”不相等”)<<endl; Sample<double> s3(2.5),s4(2.5); cout<<”s3 与 s4 的数据成员”<<(s3==s4? ”相等”:”不相等”)<<endl; } 程序执行结果: s1 与 s2 的数据成员不相等 s3 与 s4 的数据成员相等 5