exception是c++标准库组件抛出的各种异常的基类,在c++开发的过程中我们经常会遇到各种各样的异常比如,打开文件失败,数组越界,等等,如果不想让程序崩溃,那么就需要使用一个异常类来处理这些异常错误,使得程序继续运行。下面我们来学习exception的基本使用。
1.异常的使用示例
我们先来看一个不使用exception的程序
- #include
- #include
- #include
-
- using namespace std;
-
- class Polymorphic
- {
- virtual void member() {}
- };
-
-
- int main()
- {
-
- Polymorphic *pb = nullptr;
- typeid(*pb);
-
- cout << "Hello World!" << endl;
- return 0;
- }
运行

程序运行就崩溃了,然后我们再使用异常处理
- #include
- #include
- #include
-
- using namespace std;
-
- class Polymorphic
- {
- virtual void member() {}
- };
-
-
- int main()
- {
-
- try {
- Polymorphic *pb = nullptr;
- typeid(*pb);
- } catch (std::exception &e) {
- std::cerr << "exception caught: " << e.what() << endl;
- }
- cout << "Hello World!" << endl;
- return 0;
- }
运行结果:

程序抛出空指针的异常,但程序不会崩溃,因此使用exception时程序出现错误时,可以抛出来,避免程序崩溃,程序员需要处理抛出的异常。
2.current_exception捕获当前异常到exception_ptr中
- #include
- #include
-
- using namespace std;
-
-
- //1.current_exception捕获当前异常到exception_ptr中
- void handle_exception(std::exception_ptr eptr) //按值传递
- {
- try {
- if(eptr)
- std::rethrow_exception(eptr);
- } catch (const std::exception &e) {
- std::cout << "Caught exception=====" << e.what() << endl;
- }
- }
-
- int main()
- {
- std::exception_ptr eptr;
- try {
- std::string().at(1);//知成一个std::out_of_range
- } catch (...) {
- //捕获当前异常
- eptr = std::current_exception();
- }
-
- handle_exception(eptr);
- cout << "Hello World!" << endl;
- return 0;
- }
运行结果:

3.make_exception_ptr 创建一个异常对象
- #include
- #include
- #include
-
- using namespace std;
-
-
- int main()
- {
- auto p = std::make_exception_ptr(std::logic_error("logic_error"));
- try {
- std::rethrow_exception(p);
- } catch (const std::exception& e) {
- std::cout << "exception caught:" << e.what() << endl;
- }
- cout << "Hello World!" << endl;
- return 0;
- }
运行结果:

4.rethrow_exception 从一个 std::exception_ptr 抛出异常
- #include
- #include
- #include
- #include
-
- using namespace std;
-
-
- int main()
- {
- std::exception_ptr p;
- try {
- std::vector<int> myvector(10);
- myvector.at(20) = 100; //vector::at throws on out-of-range
- } catch (const std::exception& e) { //捕获异常
- cout << "e.what ======== " << e.what() << endl;
- p = current_exception();
- cout << "exception caught, but continuing... typeid(p).name ====" << typeid(p).name() << endl;
- }
- cout << "(after exception)" << endl;
- try {
- std::rethrow_exception(p);
- } catch (const std::exception& e) {
- std::cout << "exception caught: " << e.what() << endl;
- }
- cout << "Hello World!" << endl;
-
- return 0;
- }
运行结果:

5.terminate 异常终止
- #include
- #include
- #include
- #include
-
- using namespace std;
-
- int main()
- {
- char *p;
- cout << "Attempting to allocate 2GB..." << endl;
- try {
- p = new char[2147483647]; //2147483648====>2GB
- } catch (const exception &e) {
- cout << "excepter=======e.what()======= " << e.what() << endl;
- cout << "Error: could not allocate storage." << endl;
- terminate();
- }
- delete[] p;
- cout << "Hello World!" << endl;
- return 0;
- }
运行结果:

6.设置终止异常函数
- #include
- #include
- #include
- #include
-
- using namespace std;
-
-
- void myterminate()
- {
- std::cerr << "terminate handler called" << endl;
- abort(); //forces abnormal termination
- }
-
- int main()
- {
- std::set_terminate(myterminate);
- throw 0; //unhandled exception: calls terminate handler
- cout << "Hello World!" << endl;
- return 0;
- }
运行结果:

7.throw_width_nested嵌套异常
- #include
- #include
- #include
- #include
- #include
- #include
-
- using namespace std;
-
-
- void openFile(const std::string &fileName)
- {
- try {
- std::ifstream file(fileName);
- file.exceptions(std::ios_base::failbit);
- } catch (...) {
- std::cout << "openFile=====fileName===" << fileName << endl;
- std::throw_with_nested(std::runtime_error("Couldn't open " + fileName));
- }
- }
-
- //捕捉异常并将其包装于nested_exception
- void throwWithNested()
- {
- try {
- openFile("nonexistent.txt");
- } catch (const exception &e) {
- cout << "throwWithNested()====e.what===" << e.what() << endl;
- }
- }
-
- int main()
- {
- try {
- throwWithNested();
- } catch (const std::exception &e) {
- cout << "exception =====e.what====== " << e.what() << endl;
- }
- cout << "Hello World!" << endl;
- return 0;
- }
运行结果:

8.rethrow_if_nested如果是嵌套抛出异常
- #include
- #include
- #include
- #include
- #include
- #include
-
- using namespace std;
-
-
- // 打印异常的解释性字符串。若异常内嵌,则递归打印其保有的异常的解释
- void printException(const std::exception &e, int level = 0)
- {
- cout << std::string(level, ' ') << "exception: " << e.what() << endl;
- try {
- std::rethrow_if_nested(e);
- } catch (const std::exception &e) {
- printException(e, level + 1);
- }catch(...) {
- cout << "printException=======e.what== " << e.what() << " level = " << level << endl;
- }
- }
-
-
- void openFile(const std::string &fileName)
- {
- try {
- std::ifstream file(fileName);
- file.exceptions(std::ios_base::failbit);
- } catch (...) {
- std::cout << "openFile=====fileName===" << fileName << endl;
- std::throw_with_nested(std::runtime_error("Couldn't open " + fileName));
- }
- }
-
- //捕捉异常并将其包装于nested_exception
- void throwWithNested()
- {
- try {
- openFile("nonexistent.txt");
- } catch (const exception &e) {
- cout << "throwWithNested()====e.what===" << e.what() << endl;
- std::throw_with_nested(e);
- }
- }
-
- int main()
- {
-
- try {
- throwWithNested();
- } catch (const std::exception &e) {
- printException(e);
- }
- cout << "Hello World!" << endl;
- return 0;
- }
运行结果:

参考: