C++中的异常
C++中的异常主要由三个关键字构成:try
,catch
,throw
。
其中throw
抛出异常,try
包围可能发生异常的语句,catch
用来做异常处理。
看一个例子:
#include <iostream>
#include <string>
using namespace std;int main()
{try {throw(string("gaoyuelong"));}catch (string str) {cout << str << endl;}return 0;
}
throw
可以抛出任意异常,只要catch进行相应的捕获即可。
比如:
int main() {int age = 100;try {if (age > 90) {throw(age);//throw后面的语句不会被执行到cout << "123" << endl;}}catch (int age) {cout << age << " is too big" << endl;}return 0;
}
上面的例子中提到throw
后面的语句不会被执行值得注意。
异常会向外传播,直到有相应的catch
捕获异常,比如:
void inner()
{//在外层被捕获throw("123");
}void outer()
{try{inner();}catch (...){cout << "exception caught" << endl;}
}int main()
{outer();return 0;
}
如果一直向外传播都没有找到匹配的catch
捕获,程序会崩溃。catch(...)
表示捕获任意类型的异常。
如果我们想在抛出异常时,携带一些信息,帮助开发人员更好的调用调试,可以继承自exception
类,重写what
方法:
class idontknowwhatshappening : public exception
{
public:idontknowwhatshappening() = default;~idontknowwhatshappening() = default;idontknowwhatshappening& operator=(const idontknowwhatshappening&) = default;//返回const char*而不是string,string可能也会发生异常const char* what() { return "I don't know what's happening"; };
};void inner()
{try{throw(idontknowwhatshappening());}catch (idontknowwhatshappening &e){cout << e.what() << endl;}
}void outer()
{try{inner();}catch (...){cout << "exception caught" << endl;}
}
异常被捕获时,会按照catch定义的语句顺序,挨个进行匹配,执行第一个匹配完成的流程:
class idontknowwhatshappening : public exception
{
public:idontknowwhatshappening() = default;~idontknowwhatshappening() = default;idontknowwhatshappening& operator=(const idontknowwhatshappening&) = default;const char* what() const { return "I don't know what's happening"; };
};void inner()
{try{throw(idontknowwhatshappening());}catch (const idontknowwhatshappening &e){//匹配到则先执行这里cout << e.what() << endl;}catch (exception &e){cout << "e" << endl;}//而如果父类exception先进行捕获的话,就先执行父类的捕获//catch按顺序执行,他会执行第一个能匹配到的捕获/*catch (exception &e){cout << "e" << endl;}catch (const idontknowwhatshappening &e){cout << e.what() << endl;}*/
}
如果异常在被第一个catch
捕获时,需要修改对象的值,这时需要引用对象:
class i : public exception
{
public:i() = default;~i() = default;i& operator=(const i&) = default;const char* what() { return "exception i"; }string s;
};void outer()
{try{throw i();}catch (i& I)//这里使用引用{I.s = "123";cout << "exception caught" << endl;cout << I.s << endl;}
}
若当前catch
发现处理不了异常,需要继续向上传递时,使用throw
:
void outer()
{try{throw i();}catch (i& I){I.s = "123";cout << "exception caught" << endl;cout << I.s << endl;//继续向上层抛出throw;}
}int main() {try{outer();}catch (i &I){cout << "main: " << I.s << endl;}return 0;
}
如果一个函数我们确保他不会发生异常,可以使用noexcept
关键字,这样编译器可能会对这个函数做一些不会抛出异常的优化
//用noexcept修饰后,不能再抛出异常了,否则程序会崩溃
const char* foo() noexcept
{throw("123");
}int main()
{try {foo();}catch (...){cout << "exception caught" << endl;}return 0;
}
关于异常的编码规范,一般关于异常的处理都放在外面做,而函数自身,只需要进行检查,若不符合规范抛出异常让外层处理。比如:
void Process(int n)
{if (n > 3){//去外面处理,不要在使用方处理throw runtime_error("number too big");}
}int main()
{vector<int> v = {1, 2, 3, 4, 5};for (int i = 0; i < 5; i++){try {Process(v[i]);cout << v[i] << endl;}catch(runtime_error &e){cout << e.what() << endl;}}return 0;
}
以上,便是对C++中异常的一些基础使用,希望对你有用。
如果你觉得文章还不错,欢迎点赞评论哦!关注账号,你还会收到关于C++的更多知识哦!!