【C++ Primer】第十五章 友元、异常和其他 --之二--->异常
一,运行阶段错误
1)程序打开一个不可用的文件
2)请求过多的内存
3)遭遇不能容忍的值
二,调用abort() 异常终止一个进程 #include <stdlib.h>
流程: 1)向标准错误流发送消息 abnormal program termination
2)终止程序
3)返回一个随实现而异的值,告诉OS或父进程,处理失败
#include <cstdlib> int main() { abort(); return 0; }
三,异常机制
1)例子:
#include <iostream> using namespace std; double hmean(double a,double b) { if(a == -b) throw "bad hmean() a=-b"; return 2*a*b/(a+b); } int main() { double x,y,z; cout<<"Enter two numbers: "; while(cin>>x>>y) { try{ z=hmean(x,y); }catch(const char *s){ cout<<s<<endl; cout<<"Enter next set of numbers :"; continue; } cout<<"Harmonic mean of "<<x<<" and "<<y<<" is "<<z<<endl; cout<<"Enter next pair of numbers: <q to quit>"; } cout<<"Bye!\n"; return 0; }说明:throw 类似于执行返回语句,它终止函数的执行。但throw不是将控制权返回给调用程序,而是导致程序沿函数调用序列后退。直到找到try块的函数。
2)exception类
捕获所有异常:catch(...){ }
异常的注意事项:1>使用异常会增加程序代码
2>降低程序的运行速度
3>异常规范不适用于模板,模板引发的异常随特定具体化而异
三,RTTI (runtime type identification) 运行阶段类型识别
1)含义:程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型
2)RTTI提供了以下两个非常有用的操作符:
1)typeid操作符,返回指针和引用所指的实际类型;typeid(a).name()就能知道变量a是什么类型的 2)dynamic_cast操作符,将基类类型的指针或引用安全地转换为派生类型的指针或引用。3)例子:
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; class Grand { private: int hold; public: Grand(int h=0):hold(h){} virtual void speak() const { cout<<"I am a grand class!\n"; } virtual int Value()const{ return hold; } }; class Superb:public Grand { public: Superb(int h=0):Grand(h){} void speak() const { cout<<"I am a super class!\n"; } virtual void say() const{ cout<<"I hold the superb value of "<<Value()<<"!\n"; } }; class Magnificent:public Superb { private: char ch; public: Magnificent(int h=0,char cv='A'):Superb(h),ch(cv){} void speak() const { cout<<"I am a Magnificent class!\n"; } virtual void say() const{ cout<<"I hold the character "<<ch<<"and the interger"<<Value()<<"!\n"; } }; Grand *GetOne() { Grand *p; switch(rand()%3) { case 0:p=new Grand(rand()%100); break; case 1:p=new Superb(rand()%100); break; case 2:p=new Magnificent(rand()%100,'A'+rand()%26); break; } return p; } int main() { srand(time(0)); Grand *pg; Superb *ps; for(int i=0;i<5;i++) { pg=GetOne(); cout<<"Now processing type "<<typeid(*pg).name()<<".\n"; //typeid(*pg).name() 返回的是类名 pg->speak(); if(ps == dynamic_cast<Superb *> (pg)) //dynamic_cast<Superb *> (pg) 将基类类型的指针或引用安全地转换为派生类型的指针或引用 ps->say(); if(typeid(Magnificent) == typeid(*pg)) cout<<"Yes , you are really magnificent .\n"; } return 0; } 输出:(由于采用随机数,每次运行结果不同)