c++异常处理

c++异常机制相比C语言异常处理的优势:

函数的返回值可以忽略,但异常不可忽略。如果程序出现异常,但是没有被捕获,程序就会终止,这多少会促使程序员开发出来的程序更健壮一点。而如果使用C语言的error宏或者函数返回值,调用者都有可能忘记检查,从而没有对错误进行处理,结果造成程序莫名其面的终止或出现错误的结果。

2 整型返回值没有任何语义信息。而异常却包含语义信息,有时你从类名就能够体现出来。

3 整型返回值缺乏相关的上下文信息。异常作为一个类,可以拥有自己的成员,这些成员就可以传递足够的信息。

4 异常处理可以在调用跳级。这是一个代码编写时的问题:假设在有多个函数的调用栈中出现了某个错误,使用整型返回码要求你在每一级函数中都要进行处理。而使用异常处理的栈展开机制,只需要在一处进行处理就可以了,不需要每级函数都处理

异常基本语法:

忽略异常代码

#include <iostream>
using namespace std;
int DivZero_A(int a,int b)
{
	if (b == 0)
	{
		throw 0;
	}
	return a / b;
}

int DivZero_B(int a, int b)
{
	int ret = DivZero_A(a,b)+10;由于DivZero_B没有处理异常,导致B结果运算错误
	return ret;
}

int DivZero_C()
{
	int a = 10;
	int b = 0;

#if 1

	int ret = DivZero_B(a, b);//没有处理异常,程序直接中断执行,异常不能忽略

#else

	try
	{
		int ret = DivZero_B(a, b);
	}
	catch (int e)
	{
		cout << "  DivZero_C Call  DivZero_B 除数为:" << e << endl;
	}

#endif
	return 0;
}
int main()
{
	DivZero_C();
	system("pause");
	return 0;
}

运行中断:


把#if 1改为 0代码就处理异常了,程序可以运行,结果如下:



总结:

1若有异常则通过throw操作创建一个异常对象并抛出

将可能抛出异常的程序段放到try块之中

如果在try段执行期间没有引起异常,那么跟在try后面的catch字句就不会执行

4 catch子句会根据出现的先后顺序被检查,匹配的catch语句捕获并处理异常(或继续抛出异常)

如果匹配的处理未找到,则运行函数terminate将自动被调用,其缺省功能调用abort终止程序

处理不了的异常,可以在catch的最后一个分支,使用throw,向上抛

 

c++异常处理使得异常的引发和异常的处理不必在一个函数中,这样底层的函数可以着重解决具体问题,而不必过多的考虑异常的处理。上层调用者可以在适当的位置设计对不同类型异常的处理,也就是《C++ primer》中说的:将问题检测和问题处理相分离



c++异常机制和函数机制互不干涉,但是捕捉方式是通过严格类型匹配

#include <iostream>
using namespace std;
#include<string>
void throw_test()
{
	cout << "抛出异常开始" << endl;
	
	string S2= "throw string extremely";//抛出char* 类型异常
	//throw 'a';//抛出char类型异常
	//throw "char*  extremely";
	throw S2;

}


void try_test()
{
	try
	{
		throw_test();
	}
	catch (char e)
	{
		cout << "抛出char类型异常" << endl;
	}
	catch (char* e)
	{
		cout << "抛出char*类型异常" << endl;
	}
	catch (string e)
	{
		cout << "抛出string类型异常" << endl;
	}
	//捕获所有异常
	catch (...){
		cout << "抛出其他类型异常!" << endl;
	}
}
int main()
{
	try_test();
	system("pause");
	return 0;
}
运行结果:




栈解旋:异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反,这一过程称为栈的解旋(unwinding)

代码如下:

#include <iostream>
using namespace std;
#include<string>
class person
{
public:
	person(string name)
	{
		cout << "person构造函数" << endl;
		this->name = name;
	}
	~person()
	{
		cout << "person析构函数" << endl;
		
	}
public:
	string name;

};

void test_person()
{
	person p1("one");
	person p2("two");
	person p3("three");
	throw 3;
}
int main()
{
	try
	{
		test_person();
	}
	catch (int e)
	{
		cout << "异常被捕获" << endl;
	}
	system("pause");
	return 0;
}

结果如图:抛出之前创建的三个对象全部自动析构,然后才调用异常





c++标准异常

1 logic_error类及其子类、runtime_error类及其子类,它们的构造函数是接受一个string类型的形式参数,用于异常信息的描述

2 所有的异常类都有一个what()方法,返回const char* 类型(C风格字符串)的值,描述异常信息

#include<iostream>
using namespace std;
#include<stdexcept>
class person
{
public:
	person(int age)
	{
		if (age<1 || age>30)
		{
			throw out_of_range("年龄应该在1-30岁之间");//这是超出有效范围的异常类,标准异常类都有一个描述异常信息的有参构造函数
		}
		this->age = age;
	}
public:
	int age;

};

void test_stdexcept()
{
	try
	{
		person p(0);
	}
	catch (out_of_range& ex)
	{
		cout << ex.what() << endl;//标准异常类的what方法打印异常信息
	}
	
}

int main()
{
	test_stdexcept();
	system("pause");
	return 0;

}

结果打印异常信息




借助标准异常类写一个自己的异常处理类

1exception:所有标准异常类的父类

2当继承标准异常类时,应该重载父类的what函数和虚析构函数

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<stdexcept>
#include <string>

//自己的异常类
class myout_of_range :public exception
{
public:
	myout_of_range(char* str)
	{
		pError = new char[strlen(str) + 1];
		strcpy(pError, str);
	}

	virtual const char* what()
	{
		return pError;
	}

	~myout_of_range()
	{
		if (pError != NULL)
		{
			delete pError;
		}
	}
public:
	char* pError;

};


//使用自己的异常类
class person
{
public:
	person(int age)
	{
		if (age<1 || age>30)
		{
			throw myout_of_range("年龄应该在1-30岁之间");
		}
		this->age = age;
	}
public:
	int age;

};

void test_stdexcept()
{
	try
	{
		person p(0);
	}
	catch (myout_of_range& ex)
	{
		cout << ex.what() << endl;
	}
}
int main()
{
	test_stdexcept();
	system("pause");
	return 0;

}

打印结果:







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值