image.png

用try、catch处理异常

  1. #include <iostream>
  2. using namespace std;
  3. int main() {
  4. double m, n;
  5. cin >> m >> n;
  6. try {
  7. cout << "before dividing." << endl;
  8. if(n == 0)
  9. throw -1; // 抛出int类型异常
  10. else
  11. cout << m / n << endl;
  12. cout << "after dividing." << endl;
  13. } catch (double d) {
  14. cout << "catch(double)" << endl;
  15. } catch(int e) {
  16. cout << "catch(int)" << endl;
  17. }
  18. cout << "finished." << endl;
  19. }
  20. /************* 输入
  21. 9 6
  22. ************** 输出
  23. before dividing.
  24. 1.5
  25. after dividing.
  26. finished.
  27. **************/
  • try 块中一旦抛出异常,下面的语句不再执行
  • 如果 try 中没有抛出异常,则一个 catch 也不会执行

    • 就算抛出异常,但是 catch 捕获的类型不匹配,也不会执行
    • 如果存在多个 catch 块,则根据类型从上到下以此匹配

      … 捕获任何异常

      1. #include <iostream>
      2. using namespace std;
      3. int main() {
      4. double m, n;
      5. cin >> m >> n;
      6. try {
      7. cout << "before dividing." << endl;
      8. if(n == 0)
      9. throw -1; // 抛出int类型异常
      10. else if (m == 0)
      11. throw -1.0; // 抛出double类型异常
      12. else
      13. cout << m / n << endl;
      14. cout << "after dividing." << endl;
      15. } catch (double d) {
      16. cout << "catch(double)" << d << endl;
      17. } catch(...) { // 捕获任何类型异常
      18. cout << "catch(...)" << endl;
      19. }
      20. cout << "finished." << endl;
      21. }
      22. /************* 输入
      23. 9 0
      24. 0 6
      25. ************** 输出
      26. before dividing.
      27. catch(...)
      28. finished.
      29. before dividing.
      30. catch(double)-1
      31. finished
      32. **************/

      异常再抛出

      如果一个函数在执行的过程中,抛出的异常在本函数内就被 catch 块捕获并处理了,那么该异常就不会抛给这个函数的调用者(也称“上一层的函数” );如果异常在本函数中没被处理,就会被抛给上一层的函数

      1. #include <iostream>
      2. #include <string>
      3. using namespace std;
      4. class CException {
      5. public:
      6. string msg;
      7. CException(string s):msg(s){}
      8. };
      9. double Divide(double x, double y) {
      10. if(y == 0)
      11. throw CException("divided by zero");
      12. cout << "in Divide" << endl;
      13. return x / y;
      14. }
      15. int CountTax(int salary) {
      16. try {
      17. if(salart < 0)
      18. throw -1;
      19. cout << "counting tax" << endl;
      20. } catch(int) {
      21. cout << "salary < 0" << endl;
      22. }
      23. cout << "tax counted" << endl;
      24. return salary * 0.15;
      25. }
      26. int main() {
      27. double f = 1.2;
      28. try {
      29. CountTax(-1);
      30. f = Divide(3, 0); // 没有修改f的值
      31. cout << "end of try block" << endl;
      32. }
      33. catch(CException e) {
      34. cout << e.msg << endl;
      35. }
      36. cout << "f=" << f << endl;
      37. cout << "finished" << endl;
      38. return 0;
      39. }
      40. /************** 输出
      41. salary < 0
      42. tax counted
      43. diveded by zero
      44. f=1.2
      45. finished
      46. **************/

      C++标准异常类

      image.png

      bad_cast

      在用 dynamic_cast 进行从多态基类对象(或引用) ,到派生类的引用的强制类型转换时,如果转换是不安全的,则会抛出此异常

      1. #include <iostream>
      2. #include <stdexcept>
      3. #include <typeinfo>
      4. using namespace std;
      5. class Base
      6. {
      7. virtual void func(){}
      8. };
      9. class Derived : public Base
      10. {
      11. public:
      12. void Print() { }
      13. };
      14. void PrintObj(Base & b) {
      15. try {
      16. Derived & rd = dynamic_cast<Derived &>(b);
      17. // 此转换若不安全,会抛出bad_cast异常
      18. rd.Print();
      19. } catch(bad_cast& e) {
      20. cout << e.what() << endl;
      21. }
      22. }
      23. int main() {
      24. Base b;
      25. PrintObj(b);
      26. reutnr 0;
      27. }
      28. // 输出 Bad dynamic_cast

      bad_alloc

      在用 new 运算符进行动态内存分配时,如果没有足够的内存,则会引发此异常

      1. #include <iostream>
      2. #include <stdexcept>
      3. using namespace std;
      4. int main() {
      5. try {
      6. char * p = new char[0x7ffffff]; // 无法分配这么多空间,会抛出异常
      7. } catch (bad_alloc& e) {
      8. cout << e.what() << endl;
      9. }
      10. return 0;
      11. }
      12. // 输出 bad allocation

out_of_range

vectorstringat 成员函数根据下标访问元素时,如果下标越界,就会抛出此异常

  1. #include <iostream>
  2. #include <stdexcept>
  3. #include <string>
  4. #include <vector>
  5. int main() {
  6. vector<int> v(10);
  7. try {
  8. v.at(100) = 100; // 抛出异常
  9. } catch(out_of_range& e) {
  10. cerr << e.what() << endl;
  11. }
  12. string s = "Hello";
  13. try {
  14. char c = s.at(100); // 抛出异常
  15. } catch(out_of_range& e) {
  16. cerr << e.what() << endl;
  17. }
  18. return 0;
  19. }
  20. /***************** 输出
  21. invalid vector<T< subscript
  22. invalid string position
  23. ******************/