本篇作为C++基础知识的最后一篇,介绍如何进行代码中的异常处理。
我们在写代码的过程中,不得不考虑一些突发的情况。比如说申请内存时内存不够用了,做除法时除数为0,这些都是在运行的时候才会出现的,这时候就需要考虑在运行时出现这些情况应该怎么处理。异常处理是为了程序的鲁棒性提出的一个要求,产生的语法。在C++中使用的较少,但是在Java中到处都是,因为java中的要求更加严格。
总结:
- 为了程序的健壮性,建议使用
try{}catch(){}
将代码包裹,从而在出现异常时可以被程序接到,而不会造成程序阻塞及崩溃。 - 在写
try{}catch(){}
之前需要在VS
中打开设置 - 可以通过人为指定的方式,抛出指定类型的异常
- 在
main
函数中可以进行最终的异常接收补救 - 常用
stl
中的exception类
来接收异常
1.为什么需要异常处理?
以下代码中,函数进行一个除法运算,本身是没有什么问题,但是用户在进行操作时可能会使用
foo(1, argc - 1);
的方式,
argc
默认值为
1
,因此就导致运行时传递到函数内的
n=0
,就会报错。
#include <iostream>
using namespace std;
void foo(int m, int n)
{
//异常处理
int t = m / n;
}
//argc默认为1
int main(int argc, char* argv[])
{
foo(1, argc - 1);
return 0;
}
运行结果:
出现上面的结果是谁的错呢?好像都没错,函数和用户都是正常使用。由于只有在程序运行时才可以知道会不会出错误,所以此时我们需要对异常进行一个获取,从而使得程序不至于运行时崩溃。
2.C++中异常处理如何写?
一般我们使用以下结构获取异常
try{
}
catch (...){
}
3.VS编译器的设置
除了写代码,VS中还需要进行如下设置,异常才能被catch
到。
4.如何抛异常,异常的类型?
上面代码中程序将异常抛出,操作器可以检测到异常,但是不知道如何去处理异常,它会将异常抛出给
catch
进行处理。通过对代码的修改,可以让程序获取到异常,并进行处理。
#include <iostream>
using namespace std;
void foo(int m, int n)
{
//在写代码的过程中,利用try、catch包住代码,catch就可以捕捉显示异常
//异常处理
try {
//抛出异常
int t = m / n;
}
//...代表处理所有类型的异常
catch (...) {
cout << "error"<<endl;
}
}
//argc默认为1
int main(int argc, char* argv[])
{
foo(1, argc - 1);
return 0;
}
运行结果:跳入catch()
函数中
在写代码的过程中,利用try、catch
包住代码,catch
就可以捕捉显示异常,而catch (...)
中的...
代表处理所有类型的异常。
- 常见的异常中还有一种空指针异常,其异常也是可以被接住。
#include <iostream>
using namespace std;
void foo(int m, int n)
{
//在写代码的过程中,利用try、catch包住代码,catch就可以捕捉显示异常
//异常处理
try {
//0xc0000005异常,指针访问异常,地址不存在或异常
char* p = nullptr;//空指针异常
*p = 123;
}
//...代表处理所有类型的异常
catch (...) {
cout << "error"<<endl;
}
}
运行结果:
在我们利用VS
写代码时一定要记得打开捕获程序异常的设置,并将代码利用try、catch
包住,程序的兼容性得到一个很大的提高,再也不会被随机拥堵了。
5.人为抛出异常的方法
有时候我们需要人为的去抛异常,可以使用
throw
抛出多种类型的异常。
#include <iostream>
using namespace std;
void foo(int m, int n)
{
//在写代码的过程中,利用try、catch包住代码,catch就可以捕捉显示异常
//异常处理
try {
//人为抛异常
throw 1;
throw "Hello";
}
//...代表处理所有类型的异常
catch (...) {
cout << "error"<<endl;
}
}
//argc默认为1
int main(int argc, char* argv[])
{
foo(1, argc - 1);
return 0;
}
运行结果:catch()
将所有人为抛出的异常接住
异常本质上是有数据类型的,像上面写到的,可以是int、floa
t等,使用...
代表所有类型的异常都可以被接住。
5.1人为抛出指定数据类型异常的方法
当想接住某种类型的异常,可以在
catch()
中写出对应的类型名,具体写法如下:
#include <iostream>
using namespace std;
void foo(int m, int n)
{
//在写代码的过程中,利用try、catch包住代码,catch就可以捕捉显示异常
//异常处理
try {
//人为抛异常
throw 1;
throw "Hello";
}
catch (int n) {
//在catch块中写出你所关心的异常类型
//获取throw 1;的异常,因为1为int型
cout << n << endl;
}
//...代表处理所有类型的异常
catch (...) {
cout << "error"<<endl;
}
}
//argc默认为1
int main(int argc, char* argv[])
{
foo(1, argc - 1);
return 0;
}
运行结果:可以看到catch(int n)
接到了int
类型的异常,但是n
值并不是1
(只是接到异常,并不是值传递)
5.2人为抛出的异常与接收不符时会崩溃
当抛出的异常与
catch
可接的异常数据类型不一致时,就会导致程序崩溃,如下抛出一个
"Hello"
,但是
catch
可以接的是
int
,就会造成崩溃。
#include <iostream>
using namespace std;
void foo(int m, int n)
{
//在写代码的过程中,利用try、catch包住代码,catch就可以捕捉显示异常
//异常处理
try {
//人为抛异常
//throw 1;
throw "Hello";
}
catch (int n) {
//在catch块中写出你所关心的异常类型
//获取throw 1;的异常,因为1为int型
cout << n << endl;
}
//...代表处理所有类型的异常
//catch (...) {
// cout << "error"<<endl;
//
//}
}
//argc默认为1
int main(int argc, char* argv[])
{
foo(1, argc - 1);
return 0;
}
运行结果:程序崩溃
这是因为,C++中的异常处理机制,当程序去抛异常时,会找最近的catch去接,最近的接不住,就会向外去抛出异常
。
6.在main函数中进行最后异常接收补救
下面代码中在客户端写了
catch
去接异常,也是可以接住的
#include <iostream>
using namespace std;
void foo(int m, int n)
{
//在写代码的过程中,利用try、catch包住代码,catch就可以捕捉显示异常
//异常处理
try {
//人为抛异常
//throw 1;
throw 1.0f;
//throw "Hello";
}
catch (int n) {
//在catch块中写出你所关心的异常类型
//获取throw 1;的异常,因为1为int型
cout << n << endl;
}
}
//argc默认为1
int main(int argc, char* argv[])
{
try {
foo(1, argc - 1);
}
catch (float f) {
cout << f << endl;
}
return 0;
}
运行结果:main
中的catch
函数接住异常
假如程序出现异常无法接住,我们可以在main
中使用...
做最后的补救,否则出现异常后,程序只能体面的退出。
int main(int argc, char* argv[])
{
try {
foo(1, argc - 1);
}
catch (float f) {
cout << f << endl;
}
catch (...) {
cout <<"error"<< endl;
}
return 0;
}
运行结果:
7.stl中的exception类
catch()
中除了可以写上面的基本数据类型,还可以写类类型,常见的在
stl
中一种异常处理的种类,叫做
exception类
,就会抛出一个
exception类对象
,通常我们会通
过exception类对象抛出异常的内容
,以供分析。以下
throw std::exception("123");
中
123
代表异常信息,
e.what()
将异常信息打印出来。
#include <iostream>
using namespace std;
void foo(int m, int n)
{
//在写代码的过程中,利用try、catch包住代码,catch就可以捕捉显示异常
//异常处理
try {
//人为抛异常
//throw 1;
//throw 1.0f;
//throw "Hello";
}
catch (int n) {
//在catch块中写出你所关心的异常类型
//获取throw 1;的异常,因为1为int型
cout << n << endl;
}
}
//argc默认为1
int main(int argc, char* argv[])
{
try {
foo(1, argc - 1);
throw std::exception("123");
}
//可以写出类对象,exception异常类种类
catch (std::exception& e) {
cout << e.what() << endl;
}
return 0;
}
运行结果:打印出异常信息
一般而言,我们抛出的异常不是Int
等,而是一个exception
类型来携带一个字符串,exception
是一个父类,抛出的异常可以是子类,最终使用exception
来接。
- 如果
catch(){}
中再去抛出异常,同样可以使用在外的catch
来接。
8.学习视频地址:C++57个入门知识点_57 异常处理