九、C++之异常处理
一、异常的基本使用
try 视图执行, try{}中的内容
在可能出现异常的地方,抛出异常 throw
try下面的catch捕获异常
catch(捕获类型) ... 代表所有类型
如果不想抛出异常,继续向上抛出 throw
如果没有任何处理异常的地方,那么成员调用 terminate函数,中断
自定义异常类可以抛出自定义的对象(一般匿名对象)
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class MyException { public: void printError() { cout << "自定义异常类" << endl; } }; int myDivede(int a, int b) { if (b == 0) { // return -1; //throw -1; // 抛出 int类型的异常 // throw 3.14; // 抛出double类型的异常, 异常必须处理,如果不处理就会报错 throw MyException(); // 匿名对象 } return a / b; } void test() { int a = 10; int b = 0; try { myDivede(a, b); } catch (int) // 捕获 int类型的错误 { cout << "int类型异常捕获" << endl; } catch (double) { throw 'a'; cout << "double类型异常捕获" << endl; // 如果不想处理这个异常,可以继续向上抛出 } catch (MyException e) { e.printError(); } catch (...) { cout << "其他类型异常捕获" << endl; } } int main() { try { test(); } catch (double) { cout << "main 函数中double类型异常捕获" << endl; } catch (...) { cout << "main函数中其他类型异常捕获" << endl; } return EXIT_SUCCESS; }
/* 从 try开始,到throw抛出异常之前, 所有栈上的对象,都会被释放,这个过程被称为 栈解旋, 栈上构造和析构的顺序相反 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class MyException { public: void printError() { cout << "自定义异常类" << endl; } }; class Person { public: Person() { cout << "Person的构造" << endl; } ~Person() { cout << "Person的析构" << endl; } }; int myDivede(int a, int b) { if (b == 0) { // 栈解旋 从 try开始,到throw抛出异常之前, 所有栈上的对象,都会被释放,这个过程被称为 栈解旋, 构造和析构的顺序相反 Person p1; Person p2; throw MyException(); } return a / b; } void test() { int a = 10; int b = 0; try { myDivede(a, b); } catch (MyException e) { e.printError(); /* Person的构造 Person的构造 Person的析构 Person的析构 自定义异常类 */ } } int main() { test(); return EXIT_SUCCESS; }
/* void func() throw(int, cahar) 只能抛出int,char类型的异常 此功能只能在 Qt或者linux下运行, 在visual studio下运行没有效果 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; void func() throw(int) // 代表只能抛出int类型的异常, throw()代表不抛出任何类型的异常 { throw -1; } int main() { try { func(); } catch (int) { cout << "int类型的异常" << endl; } return EXIT_SUCCESS; }
/* MyException e 这一步会调用调用拷贝构造, 会多开销一份数据 MyException *e 需要new出来, 如果是不是new MyException()出来的, 是通过 &MyException(),就会提前释放对象, new出来以后需要自己 delete MyException &e 推荐使用, 而且就产生一份数据 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class MyException { public: MyException() { cout << "Preson的默认构造" << endl; } MyException(const MyException &p) { cout << "Person的拷贝构造" << endl; } ~MyException() { cout << "Person的析构" << endl; } }; void doWork() { throw MyException(); } void test() { try { doWork(); } catch (MyException e) // 这一步会调用调用拷贝构造, 会多开销一份数据 { cout << "异常捕获" << endl; } } void test02() { try { doWork(); } catch (MyException &e) // 采用引用的方式, 让异常跑出来的对象在此接收 { cout << "异常捕获" << endl; } } void doWork02() { throw new MyException(); // 抛出指针 } void test03() { try { doWork02(); } catch (MyException *e) { cout << "异常捕获" << endl; delete e; // 需要自己释放对象 } } int main() { test(); /* Preson的默认构造 Person的拷贝构造 异常捕获 Person的析构 Person的析构 */ test02(); // 推荐使用方式 /* Preson的默认构造 异常捕获 Person的析构 */ test03(); /* Preson的默认构造 异常捕获 Person的析构 */ return EXIT_SUCCESS; }
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; // 异常基类 class BaseException { public: virtual void printError() { } }; class NullPonitException : public BaseException { public: virtual void printError() { cout << "空指针异常" << endl; } }; class OutoRangeException : public BaseException { public: virtual void printError() { cout << "越界异常" << endl; } }; void doWork() { throw NullPonitException(); } void test() { try { doWork(); } catch (BaseException & e) { e.printError(); } } int main() { test(); return EXIT_SUCCESS; }
二、C++标准异常库
2.1 使用系统提供的标准异常
/* #include<stdexcept> throw out_of_range("年龄越界"); catch (out_of_range &e) e.what() */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; // 使用系统提报标准异常 #include<stdexcept> class Person { public: Person(string name, int age) { this->Name = name; if (age < 0 || age > 200) { // 抛出越界异常 throw out_of_range("年龄越界"); } } string Name; int Age; }; void test() { try { Person p1("wangyong", 520); } catch (out_of_range &e) { cout << e.what() << endl; // 年龄越界 } } int main() { test(); return EXIT_SUCCESS; }
/* 自己的遗产类需要继承于 exception 重写 虚析构 what() 内部维护错误信息字符串 构造时候传入错误信息字符串, what返回 string转char * : c_str() */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class MyOutOfRangeException : public exception // exception 系统提供的异常类 { public: MyOutOfRangeException(string errorInfo) { this->Error = errorInfo; } virtual ~MyOutOfRangeException() { } virtual const char * what() { // string转char * return this->Error.c_str(); } string Error; }; class Person { public: Person(string name, int age) { this->Name = name; if (age < 0 || age > 200) { throw MyOutOfRangeException("年龄越界"); } } string Name; int Age; }; void test() { try { Person p1("wangyong", 520); } catch (MyOutOfRangeException &e) { cout << e.what() << endl; // 年龄越界 } } int main() { test(); return EXIT_SUCCESS; }