例14.1 给出三角形的三边a,b,c,求三角形的面积。只有a+b>c,b+c>a,c+a>b时才能构成三角形。设置异常处理,对不符合三角形条件的输出警告信息,不予计算。
先写出没有异常处理时的程序:
#include <iostream>
#include <cmath>
usingnamespacestd;
intmain( )
{doubletriangle(double,double,double);
doublea,b,c;
cin>>a>>b>>c;
while(a>0&& b>0&& c>0)
{cout<<triangle(a,b,c)<<endl;
cin>>a>>b>>c;
}
return0;
}
doubletriangle(doublea,doubleb,doublec)
{doublearea;
doubles=(a+b+c)/2;
area=sqrt(s*(s-a)*(s-b)*(s-c));
returnarea;
}
修改后的程序如下:
#include <iostream>
#include <cmath>
usingnamespacestd;
voidmain( )
{doubletriangle(double,double,double);
doublea,b,c;
cin>>a>>b>>c;
try//在try块中包含要检查的函数
{while(a>0&& b>0&& c>0)
{cout<<triangle(a,b,c)<<endl;
cin>>a>>b>>c;
}
}
catch(double) //用catch捕捉异常信息并作相应处理
{cout<<"a="<<a<<",b="<<b<<",c="<<c<<",that is not a triangle!"<<endl;}
cout<<"end"<<endl;
}
doubletriangle(doublea,doubleb,doublec) //计算三角形的面积的函数
{doubles=(a+b+c)/2;
if(a+b<=c||b+c<=a||c+a<=b) throwa; //当不符合三角形条件抛出异常信息
returnsqrt(s*(s-a)*(s-b)*(s-c));
}
例14.2 在函数嵌套的情况下检测异常处理。
这是一个简单的例子,用来说明在try块中有函数嵌套调用的情况下抛出异常和捕捉异常的情况。请自己先分析以下程序。
#include <iostream>
usingnamespacestd;
intmain( )
{voidf1( );
try
{f1( );}//调用f1( )
catch(double)
{cout<<"OK0!"<<endl;}
cout<<"end0"<<endl;
return0;
}
voidf1( )
{voidf2( );
try
{f2( );} //调用f2( )
catch(char)
{cout<<"OK1!";}
cout<<"end1"<<endl;
}
voidf2( )
{voidf3( );
try
{f3( );} //调用f3( )
catch(int)
{cout<<"Ok2!"<<endl;}
cout<<"end2"<<endl;
}
voidf3( )
{doublea=0;
try
{throwa;} //抛出double类型异常信息
catch(float)
{cout<<"OK3!"<<endl;}
cout<<"end3"<<endl;
}
例14.3 在异常处理中处理析构函数。
这是一个为说明在异常处理中调用析构函数的示例,为了清晰地表示流程,程序中加入了一些cout语句,输出有关的信息,以便读者对照结果分析程序。
#include <iostream>
#include <string>
usingnamespacestd;
classStudent
{public:
Student(intn,string nam)//定义构造函数
{cout<<"constructor-"<<n<<endl;
num=n;name=nam;}
~Student( ){cout<<"destructor-"<<num<<endl;}//定义析构函数
voidget_data( ); //成员函数声明
private:
intnum;
string name;
};
voidStudent::get_data( ) //定义成员函数
{if(num==0) thrownum; //如num=0,抛出int型变量num
elsecout<<num<<" "<<name<<endl; //若num≠0,输出num,name
cout<<"in get_data()"<<endl; //输出信息,表示目前在get_data函数中
}
voidfun( )
{Student stud1(1101,"Tan"); //建立对象stud1
stud1.get_data( ); //调用stud1的get_data函数
Student stud2(0,"Li"); //建立对象stud2
stud2.get_data( ); //调用stud2的get_data函数
}
intmain( )
{cout<<"main begin"<<endl; //表示主函数开始了
cout<<"call fun( )"<<endl; //表示调用fun函数
try
{fun( );} //调用fun函数
catch(intn)
{cout<<"num="<<n<<",error!"<<endl;} //表示num=0出错
cout<<"main end"<<endl; //表示主函数结束
return0;
}
例14.4 名字冲突。
程序员甲在头文件header1.h中定义了类Student和函数fun。
//header1.h (头文件1,设其文件名为cc14-4-h1.h)
#include <string>
#include <cmath>
usingnamespacestd;
classStudent//声明Student类
{public:
Student(intn,string nam,chars)
{num=n;name=nam;sex=s;}
voidget_data( );
private:
intnum;
string name;
charsex;
};
voidStudent::get_data( ) //成员函数定义
{cout<<num<<" "<<name<<" "<<sex<<endl;
}
doublefun(doublea,doubleb) //定义全局函数(即外部函数)
{returnsqrt(a+b);}
在main函数所在的文件中包含头文件header1.h:
#include <iostream>
#include "cc14-4-h1.h" //注意要用双引号,因为文件一般是放在用户目录中的
usingnamespacestd;
intmain( )
{Student stud1(101,"Wang",18); //定义类对象stud1
stud1.get_data( );
cout<<fun(5,3)<<endl;
return0;
}
例14.5 利用命名空间来解决例14.4程序名字冲突问题。
修改两个头文件,把在头文件中声明的类分别放在两个不同的命名空间中。
//header1.h (头文件1)
#include <string>
#include <cmath>
usingnamespacestd;
namespacens1//声明命名空间ns1
{classStudent //在命名空间ns1内声明Student类
{public:
Student(intn,string nam,inta)
{num=n;name=nam;age=a;}
voidget_data( );
private:
intnum;
string name;
intage;
};
voidStudent::get_data() //定义成员函数
{cout<<num<<" "<<name<<" "<<age<<endl;
}
doublefun(doublea,doubleb) //在命名空间ns1内定义fun函数
{returnsqrt(a+b);}
}
//header2.h ((头文件2)
#include <string>
#include <cmath>
usingnamespacestd;
namespacens2 //声明命名空间ns2
{classStudent
{public:
Student(intn,string nam,chars)
{num=n;name=nam;sex=s;}
voidget_data( );
private:
intnum;
charname[20];
charsex;
};
voidStudent::get_data( )
{cout<<num<<" "<<name<<" "<<sex<<endl;
}
doublefun(doublea,doubleb)
{returnsqrt(a-b);}
}
//main file (主文件)
#include <iostream>
#include "cc14-5-h1.h" //包含头文件1
#include "cc14-5-h2.h" //包含头文件2
usingnamespacestd;
intmain( )
{ns1::Student stud1(101,"Wang",18); //用命名空间ns1中声明的Student类定义stud1
stud1.get_data( ); //不要写成ns1::stud1.get_data( );
cout<<ns1::fun(5,3)<<endl; //调用命名空间ns1中的fun函数
ns2::Student stud2(102,"Li",'f'); //用命名空间ns2中声明的Student类定义stud2
stud2.get_data( );
cout<<ns2::fun(5,3)<<endl; //调用命名空间ns1中的fun函数
return0;
}