【C++】异常处理 ⑤ ( 异常类型 | 传统 C 语言中的异常处理 | C++ 异常处理 - 抛出 int 类型异常 | 捕获异常类型 / 异常变量 | C++ 异常处理 - 抛出指针类型异常 )

2023-12-02 11:00:38 浏览数 (1)

一、传统异常处理


1、C 语言中的异常处理

传统的 C 语言中 错误处理 , 是通过返回不同的 int 类型值进行的 , 如 :

  • 执行成功返回 0 ;
  • 情况一 执行失败 , 返回 1 ;
  • 情况二 执行失败 , 返回 2 ;

2、代码示例 - 传统异常处理

如下代码示例中 , 实现一个字符串拷贝功能 , 拷贝时可能遇到各种错误 , 如 : 源字符串 不符合要求 , 目的字符串不符合要求 , 拷贝过程出错等 ;

传统的 C 语言处理方式就是 : 返回 int 类型返回值 , 函数执行成功返回 0 , 不同的失败情况返回不同的返回值 ;

代码示例 :

代码语言:javascript复制
#include "iostream"
using namespace std;

// 拷贝函数 
// 返回值 int 类型的错误码
int my_strcpy(char* to, char* from) {
	if (from == NULL)
	{
		// 源字符串出错
		return 1;
	}
	if (to == NULL)
	{
		// 目标字符串出错
		return 2;
	}
	
	// 拷贝前检查条件
	if (*from == 'J') 
	{
		// 源字符串不能是 J 开头的
		return 3;
	}

	// 逐个字节拷贝字符
	while (*from != '')
	{
		*to = *from;
		to  ;
		from  ;
	}
	*to = '';

	return 0;
}

int main() {

	// 字符串拷贝函数返回值
	int ret = 0;
	// 源字符串
	char str1[] = "Tom";
	// 目的字符串
	char str2[32] = {0};

	// 调用字符串拷贝函数
	ret = my_strcpy(str2, str1);

	// 根据不同的返回值进行不同的错误处理
	switch (ret)
	{
	case 0:
		cout << "拷贝成功 : str2 : " << str2 << endl;
		break;
	case 1:
		cout << "源字符串出错" << endl;
		break;
	case 2:
		cout << "目的字符串出错" << endl;
		break;
	case 3:
		cout << "拷贝过程出错" << endl;
		break;
	default:
		cout << "位置错误" << endl;
		break;
	}

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
};

执行结果 :

代码语言:javascript复制
拷贝成功 : str2 : Tom
Press any key to continue . . .

二、C 异常处理 - 抛出 int 类型异常


1、C 异常处理

在 C 中的 错误处理 可以不占用 返回值 位置 , 使用 异常处理 机制 , 在函数中 抛出 指定类型 的异常 进行处理 ;

2、C 异常接收方式

抛出异常后 , 捕获异常 , 接收异常有很多种方式 ;

  • 可以按照 普通类型 接收异常 ,
  • 可以按照 引用类型 接收异常 ,
  • 可以按照 指针类型 接收异常 ;

3、捕获异常类型 / 异常变量

在 catch 分支中 , 捕获异常时 , 可以写 异常变量 , 也可以不写 ;

  • 不写异常变量 : 只捕获异常类型 , 如 :
代码语言:javascript复制
catch(int)

表示捕获 int 类型的异常 , 但是如果这么写了 , 只能拦截到异常 , 知道 抛出了一个 int 类型的异常 , 不能访问异常的具体内容 ;

  • 写异常变量 : 可以访问异常变量 , 知道抛出的异常值是多少 , 如 :
代码语言:javascript复制
catch(int e)

通过上面的 变量 e , 可以知道抛出的异常的具体 int 数值是多少 ;

4、代码示例 - 抛出 / 捕获 int 类型异常

代码示例 :

代码语言:javascript复制
#include "iostream"
using namespace std;

// 拷贝函数 
// 使用 throw 关键字抛出 int 类型的异常
void my_strcpy(char* to, char* from) throw(int) {
	if (from == NULL)
	{
		// 源字符串出错
		throw 1;
	}
	if (to == NULL)
	{
		// 目标字符串出错
		throw 2;
	}
	
	// 拷贝前检查条件
	if (*from == 'J') 
	{
		// 源字符串不能是 J 开头的
		throw 3;
	}

	// 逐个字节拷贝字符
	while (*from != '')
	{
		*to = *from;
		to  ;
		from  ;
	}
	*to = '';
}

int main() {

	// 源字符串
	char str1[] = "Tom";
	// 目的字符串
	char str2[32] = {0};

	try
	{
		// 调用字符串拷贝函数
		my_strcpy(str2, str1);

		cout << "拷贝成功 : str2 : " << str2 << endl;
	}
	// catch 分支中可以写 异常变量 , 也可以不写
	// 如果不写 , 则不能访问抛出的 异常对象
	catch (int e)
	{
		// 根据不同的返回值进行不同的错误处理
		switch (e)
		{
		case 1:
			cout << "源字符串出错" << endl;
			break;
		case 2:
			cout << "目的字符串出错" << endl;
			break;
		case 3:
			cout << "拷贝过程出错" << endl;
			break;
		default:
			cout << "位置错误" << endl;
			break;
		}
	}

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
};

执行结果 :

代码语言:javascript复制
拷贝成功 : str2 : Tom
Press any key to continue . . .

三、C 异常处理 - 抛出指针类型异常


抛出 / 捕获异常 , 有很多种方式 ;

  • 可以按照 普通类型 抛出 / 捕获异常 ,
  • 可以按照 引用类型 抛出 / 捕获异常 ,
  • 可以按照 指针类型 抛出 / 捕获异常 ;

上一个章节 演示了 抛出 / 捕获 普通类型 异常 , 本章节介绍 抛出 / 捕获 引用类型 异常 ;

1、抛出 char* 字符串常量 类型异常

抛出 char* 字符串 指针类型异常 操作 , 与 抛出 普通变量类型的异常 操作相同 ;

字符串常量 存储在 符号表 中 , 因此可以在所有的函数之间传递 ;

抛出 / 捕获 异常 关键代码如下 :

  • 异常接口声明 : 注意 字符串常量 的类型为 const char* ;
代码语言:javascript复制
void my_strcpy(char* to, char* from) throw(const char*)
  • 抛出 异常 : 直接抛出 字符串常量 , 不要分配内存 ;
代码语言:javascript复制
throw "源字符串出错";
  • 捕获 异常 : 捕获 字符串常量 异常时 , 不要忘了使用 const 修饰指针指向的数据 ;
代码语言:javascript复制
catch (const char* e)

2、代码示例 - 抛出 char* 字符串常量 类型异常

代码示例 :

代码语言:javascript复制
#include "iostream"
using namespace std;

// 拷贝函数 
// 使用 throw 关键字抛出 字符串类型的异常
void my_strcpy(char* to, char* from) throw(const char*) {
	if (from == NULL)
	{
		// 源字符串出错
		throw "源字符串出错";
	}
	if (to == NULL)
	{
		// 目标字符串出错
		throw "目标字符串出错";
	}
	
	// 拷贝前检查条件
	if (*from == 'J') 
	{
		// 源字符串不能是 J 开头的
		throw "源字符串不能是 J 开头";
	}

	// 逐个字节拷贝字符
	while (*from != '')
	{
		*to = *from;
		to  ;
		from  ;
	}
	*to = '';
}

int main() {

	// 源字符串
	char str1[] = "Jerry";
	// 目的字符串
	char str2[32] = {0};

	try
	{
		// 调用字符串拷贝函数
		my_strcpy(str2, str1);

		cout << "拷贝成功 : str2 : " << str2 << endl;
	}
	// catch 分支中可以写 异常变量 , 也可以不写
	// 如果不写 , 则不能访问抛出的 异常对象
	catch (const char* e)
	{
		cout << "出现异常 : " << e << endl;
	}

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
};

执行结果 :

代码语言:javascript复制
出现异常 : 源字符串不能是 J 开头
Press any key to continue . . .

0 人点赞