C++学习笔记:异常的基本语法

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

2)将可能抛出异常的程序段嵌在try块之中。控制通过正常的顺序执行到达try语句。然后执行try块内的保护段

3)如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行。程序从try块后跟随的最后一个catch子句后面的语句继续执行下去

4)catch子句按其在try块后出现的顺序被检查。匹配的catch子句将捕获并处理异常(或继续抛出异常)

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

6)处理不了的异常,可以在catch的最后一个分支,使用throw语法,向上扔

// 异常的基本语法.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

void divide(int x,int y){
	if (y == 0){
		throw x;//抛出 int 类型异常 
		//异常直接跨越函数,类似于return语句,不执行接下来的语句
	}
	cout << "divide结果:" << x / y << endl;
}

void myDivide(int x, int y){
	try{
		divide(x, y);
	}
	catch (...){
		cout << "我接受了divide的异常,但是我没有处理,我继续向上抛出" << endl;
		throw;//接受异常后可以不处理,继续抛出
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	try{
		divide(10 , 2);
		divide(100 , 0);
		//myDivide(1, 0);//跨越函数的实验
	}
	catch (int e){
		cout << e << "被零整除" << endl;
	}
	catch (...){//其他未知类型的异常
		cout << "其他未知类型异常" << endl;
	}

	return 0;
}


2.栈解旋

执行throw语句后,相当于 return ,但是不是,会调用析构函数 释放掉栈空间

// 异常_栈解旋.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

class Test{
public:
	Test(int a = 0, int b = 0){
		this->a = a;
		this->b = b;
		cout << "构造函数do" << endl;
	}
	~Test(){
		cout << "析构函数do\n";
	}
private:
	int a;
	int b;
};

void myDivide(){
	Test t1(1, 2), t2(3, 4);
	cout << "myDivide 要发生异常啦~ " << endl;
	throw 1;
}

int _tmain(int argc, _TCHAR* argv[])
{
	try{
		myDivide();
	}
	catch (int a){
		cout << "int型异常" << endl;
	}
	catch (...){
		cout << "未知异常" << endl;
	}
	return 0;
}

3.异常的接口声明

1)为了加强程序的可读性,可以在函数声明中列出可能抛出的所有异常累成,例如:

void func() throw(A,B,C,D);//这个函数func()能够且只能抛出类型A B C D及其子类型的异常

2)如果在函数声明中没有包含异常接口声明,则该函数可以抛出任何类型的异常,例如:

void func();

3)一个不抛出任何类型异常的函数可以声明为:

void func() throw();

4)如果一个函数抛出了它的异常接口声明所不允许抛出的异常,unexpercted函数会被调用,该函数默认行为调用terminate函数终止程序。


4.异常变量的声明周期

// 异常_栈解旋.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

class BadSrcType{
public:
	BadSrcType(){
		cout << "BadSrcType构造函数do" << endl;
	}
	BadSrcType(const BadSrcType &obj){
		cout << "BadSrcType拷贝构造函数do" << endl;
	}
	~BadSrcType(){
		cout << "BadSrcType析构函数do\n";
	}
};

class BadDesType{
public:
	BadDesType(){
		cout << "BadDesType构造函数do" << endl;
	}
	BadDesType(const BadDesType &obj){
		cout << "BadDesType拷贝构造函数do" << endl;
	}
	~BadDesType(){
		cout << "BadDesType析构函数do\n";
	}
};

class BadProType{
public:
	BadProType(){
		cout << "BadProType构造函数do" << endl;
	}
	BadProType(const BadProType &obj){
		cout << "BadProType拷贝构造函数do" << endl;
	}
	~BadProType(){
		cout << "BadProType析构函数do\n";
	}
};

void my_strcpy(char *to,char *from){
	if (from == NULL){
		throw BadSrcType();//会产生一个匿名对象
	}
	if (to == NULL){
		throw BadDesType();
	}
	
	if (*from=='a'){
		cout << "开始BadProType类型异常" << endl;
		throw BadProType();//适用于方式一和二
		//throw new BadProType;//适用于方式三
	}
	while (*from!='\0'){
		*to = *from;
		to++;
		from++;
	}
	*to = '\0';
}

int main()
{
	int ret = 0;
	char buf1[] = "abcdefg";
	char buf2[1024] = { 0 };
	try{
		my_strcpy(buf2,buf1);
	}
	//结论1:如果接收异常的时候使用异常变量 则进行拷贝构造异常变量
	catch (BadSrcType e){//接匿名对象,并初始化e,此时匿名对象转正,不会调用匿名对象的析构函数
		cout << "BadSrcType类型异常" << endl;
	}
	catch (BadDesType e){
		cout << "BadDesType类型异常" << endl;
	}
	catch (BadProType e){
		cout << "BadProType类型异常" << endl;
	}
	catch (...){
		cout << "未知异常" << endl;
	}
	//方式二:用引用接收异常
	//结论二:使用引用的话 会使用throw时候的那个对象
	//catch (BadSrcType &e){//接匿名对象,并初始化e,此时匿名对象转正,不会调用匿名对象的析构函数
	//	cout << "BadSrcType类型异常" << endl;
	//}
	//catch (BadDesType &e){
	//	cout << "BadDesType类型异常" << endl;
	//}
	//catch (BadProType &e){
	//	cout << "BadProType类型异常" << endl;
	//}
	//catch (...){
	//	cout << "未知异常" << endl;
	//}
	//方式三:用指针来接
	//结论三:指针可以和引用/元素 写在一块,但是元素和引用不能写在一块
	//catch (BadSrcType *e){//接匿名对象,并初始化e,此时匿名对象转正,不会调用匿名对象的析构函数
	//	cout << "BadSrcType类型异常" << endl;
	//	delete e;//在底层函数里new,在上层函数里delete。不安全
	//}
	//catch (BadDesType *e){
	//	cout << "BadDesType类型异常" << endl;
	//	delete e;
	//}
	//catch (BadProType *e){
	//	cout << "BadProType类型异常" << endl;
	//	delete e;
	//}
	//catch (...){
	//	cout << "未知异常" << endl;
	//}
	//结论:最适合的方法是用引用来接
	return 0;
}
方式一:

方式二:

方式三:



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值