【C++】异常处理 ④ ( 异常接口声明 | 异常接口语法 | 抛出一种类型的异常 | 抛出多种类型的异常 | 抛出任意类型的异常 | 不能抛出异常 | 抛出异常类型错误 | 代码示例 )

2023-12-01 09:36:30 浏览数 (2)

博客总结 :
代码语言:javascript复制
// 1. 不会抛出异常
void fun() throw();    
// 2. 可能会抛出 int 类型的异常   
void fun() throw(int);   
// 3. 可能会抛出 int 或 double 类型的异常 
void fun() throw(int, double);   
// 4. 抛出任意类型异常 
void fun() throw(...);     
// 5. 抛出任意类型异常
void fun();

一、异常接口声明

1、异常接口引入

在 C 中 , 异常可以使用 任意 类型 进行表示 , 但是 一般情况下 使用 派生自 标准异常类 std::exception 的 自定义异常类 来表示 异常 ;

" 异常接口 " 用于表示 在 函数中 要抛出的 异常类型 ;

为了 加强 程序的 可读性 , 可维护性 , 推荐将 函数 可能会抛出异常 写入到 函数的 异常接口 中,即 在 函数中国年 列出所有可能抛出的异常类型 ;

2、异常接口语法

在 C 语言中 , 异常接口 的声明使用 throw() 关键字 , 用于指定函数要抛出的异常类型 ;

异常接口语法如下 :

代码语言:javascript复制
函数返回值 函数名(函数参数列表) throw (异常类型1, 异常类型2, ..., 异常类型n)

3、抛出一种类型的异常

抛出一种类型的异常 : 在 void fun() 函数中 , 可能会抛出 int 类型的异常 , 可以使用如下异常接口声明 ;

代码语言:javascript复制
// 可能会抛出 int 类型的异常
void fun() throw(int) {
	// 函数体
}

代码示例 :

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

// 1. 在 函数 中 抛出异常
// 异常接口 : 只允许抛出 char 类型异常
void fun() throw(char) {

	cout << "开始抛出 char 类型 异常 " << endl;

	// 抛出一个 char 类型的异常
	throw 'A';
}

int main() {

	// 2. 捕获并处理异常
	try
	{
		// 调用可能产生异常的函数
		fun();
	}
	// 捕获一切未知类型的异常
	catch ( ... )
	{
		cout << "捕获到未知类型异常 ... "<< endl;
	}

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

	return 0;
};

执行结果 :

4、抛出多种类型的异常

抛出多种类型的异常 : 在 void fun() 函数中 , 可能会抛出多个类型的异常 , 可以使用如下异常接口声明 , 多个异常类型之间使用逗号隔开 ;

代码语言:javascript复制
// 可能会抛出 int , char , double 类型的异常
void fun() throw(int, char, double) {
	// 函数体
}

代码示例 :

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

// 1. 在 函数 中 抛出异常
// 异常接口 : 只允许抛出 double, int, char 类型异常
void fun() throw(double, int, char) {

	cout << "开始抛出 char 类型 异常 " << endl;

	// 抛出一个 char 类型的异常
	throw 'A';
}

int main() {

	// 2. 捕获并处理异常
	try
	{
		// 调用可能产生异常的函数
		fun();
	}
	// 捕获一切未知类型的异常
	catch ( ... )
	{
		cout << "捕获到未知类型异常 ... "<< endl;
	}

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

	return 0;
};

执行结果 :

5、抛出任何类型异常 - 不声明异常接口 / 声明 throw(…)

可抛出任何类型异常 的 函数 , 有如下两种声明方式 :

  • 不声明异常接口 : 在 函数 中 , 如果 不声明 异常接口 , 默认可以抛出任何类型的异常 ;
代码语言:javascript复制
// 1. 在 函数 中 抛出异常
void fun() {

	cout << "开始抛出 char 类型 异常 " << endl;

	// 抛出一个 char 类型的异常
	throw 'A';
}
  • 声明 throw(…) 异常接口 : 如果 函数的 异常接口 声明为 throw(…) , 则可以抛出任意类型的异常 ;
代码语言:javascript复制
// 在 函数 中 抛出任意类型异常
void fun() throw(...) {

	cout << "开始抛出 char 类型 异常 " << endl;

	// 抛出一个 char 类型的异常
	throw 'A';
}

6、不能抛出任何类型异常 - 声明 throw()

如果禁止函数抛出异常 , 则声明异常接口为 throw() , 如果 在 函数中有抛出异常的行为 , 在编译时会发出警告 ;

代码语言:javascript复制
// 不允许抛出异常
void fun() throw() {
	// 函数体
}

如果抛出了异常 , 会报错 : " 警告 C4297 “fun”: 假定函数不引发异常,但确实发生了 "

代码语言:javascript复制
严重性	代码	说明	项目	文件	行	禁止显示状态
警告	C4297	“fun”: 假定函数不引发异常,但确实发生了	HelloWorld	D:02_Project06_Visual_StudioHelloWorldHelloWorldTest.cpp	11	

代码示例 :

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

// 1. 在 函数 中 抛出异常
// 异常接口 : 不允许抛出异常
void fun() throw() {

	cout << "开始抛出 char 类型 异常 " << endl;

	// 抛出一个 char 类型的异常
	throw 'A';
}

int main() {

	// 2. 捕获并处理异常
	try
	{
		// 调用可能产生异常的函数
		fun();
	}
	// 捕获一切未知类型的异常
	catch ( ... )
	{
		cout << "捕获到未知类型异常 ... "<< endl;
	}

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

	return 0;
};

编译警告 :

代码语言:javascript复制
已启动生成…
1>------ 已启动生成: 项目: HelloWorld, 配置: Debug Win32 ------
1>Test.cpp
1>D:02_Project06_Visual_StudioHelloWorldHelloWorldTest.cpp(11,1): warning C4297: “fun”: 假定函数不引发异常,但确实发生了
1>D:02_Project06_Visual_StudioHelloWorldHelloWorldTest.cpp(11,1): message : 在函数上指定了 __declspec(nothrow)、throw()、noexcept(true)或 noexcept
1>HelloWorld.vcxproj -> D:02_Project06_Visual_StudioHelloWorldHelloWorldDebugHelloWorld.exe
1>已完成生成项目“HelloWorld.vcxproj”的操作。
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

执行结果 :

7、抛出异常类型错误

抛出异常类型错误 : 如果一个函数抛出了它的异常接口声明所不允许抛出的异常 , 会调用 unexpected 函数 , 该函数会调用 terminate 函数 中止程序 , 程序崩溃 ;

下面的 函数中 , 只能抛出 int , double 类型的异常 , 结果在 函数体中 抛出了 char 类型的异常 , 程序会发出警告 ;

代码语言:javascript复制
// 1. 在 函数 中 抛出异常
void fun() throw( double ) {

	cout << "开始抛出 char 类型 异常 " << endl;

	// 抛出一个 char 类型的异常
	throw 'A';
}

警告内容 : 0x75D5D8A2 处(位于 HelloWorld.exe 中)引发的异常: Microsoft C 异常: char,位于内存位置 0x0116F607 处。

代码示例 :

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

// 1. 在 函数 中 抛出异常
// 异常接口 : 只允许抛出 double 类型异常
void fun() throw( double ) {

	cout << "开始抛出 char 类型 异常 " << endl;

	// 抛出一个 char 类型的异常
	throw 'A';
}

int main() {

	// 2. 捕获并处理异常
	try
	{
		// 调用可能产生异常的函数
		fun();
	}
	// 捕获一切未知类型的异常
	catch ( ... )
	{
		cout << "捕获到未知类型异常 ... "<< endl;
	}

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

	return 0;
};

编译警告 :

代码语言:javascript复制
已启动生成…
1>------ 已启动生成: 项目: HelloWorld, 配置: Debug Win32 ------
1>Test.cpp
1>D:02_Project06_Visual_StudioHelloWorldHelloWorldTest.cpp(6,24): warning C4290: 忽略 C   异常规范,但指示函数不是 __declspec(nothrow)
1>HelloWorld.vcxproj -> D:02_Project06_Visual_StudioHelloWorldHelloWorldDebugHelloWorld.exe
1>已完成生成项目“HelloWorld.vcxproj”的操作。
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

执行结果 :

代码语言:javascript复制
开始抛出 char 类型 异常
捕获到未知类型异常 ...
Press any key to continue . . .

警告信息 :

代码语言:javascript复制
0x75D5D8A2 处(位于 HelloWorld.exe 中)引发的异常: Microsoft C   异常: char,位于内存位置 0x0116F607 处。

0 人点赞