【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;
}
输出:(由于采用随机数,每次运行结果不同)




         

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值