异常处理中子类和父类的捕获问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/YoungDou/article/details/46583071

问题:

原代码:

//main.cpp
#include <iostream>
#include "multi_throw.h"
#include <exception>


using namespace std;

int main() {
    int a;
    while (cin >> a) {
        try {
            multi_throw(a);
        }
        catch(logic_error ex) {
            cout << "Exception: " << ex.what() << endl;
            cout << "Exception type: class logic_error" << endl;
        }
        catch(int ex) {
            cout << "Exception: " << ex << endl;
            cout << "Exception type: int" << endl;
        }
        catch(runtime_error ex) {
            cout << "Exception: " << ex.what() << endl;
            cout << "Exception type: class runtime_error" << endl;
        }
        catch(out_of_range ex) {
            cout << "Exception: " << ex.what() << endl;
            cout << "Exception type: class out_of_range" << endl;
        }
    }
    return 0;
}

//multi_throw.h
#include <iostream>
#include <stdexcept>

void multi_throw(int i) {
     std::cout << "Input: " << i << std::endl;
     if (i <= 0) throw std::logic_error("non-positive");
     if (i <= 1) throw i;
     if (i <= 5) throw std::runtime_error("run error");
     if (i >= 9) throw std::out_of_range("too big");
}

compile error:
main.cpp: In function ‘int main()’:
main.cpp:25: error: exception of type ‘std::out_of_range’ will be caught
main.cpp:13: error: by earlier handler for ‘std::logic_error’


分析:

注意到这里编译提示了 :

by earlier handler for ‘std::logic_error’

就是说logic_error被提前处理,捕获(catch)了

这里我们需要注意一下logic_error,和out_of_range的继承关系:

exception->logic_error->out_of_range

到这里我们就明白了,由于out_of_range是继承于logic_error的,所以在抛出out_of_range类的异常时,

   catch(logic_error){
       ...;
   }

也可以捕获out_of_range,导致下列代码失效:

    catch(out_of_range ex) {
          cout << "Exception: " << ex.what() << endl;
          cout << "Exception type: class out_of_range" << endl;
    }

解决办法:

只需要改变catch的顺序,使得抛出out_of_range时不被logic_error捕获就好
代码如下:

//main.cpp
#include <iostream>
#include "multi_throw.h"
#include <exception>

using namespace std;

int main() {
    int a;
    while (cin >> a) {
        try {
            multi_throw(a);
        }
        catch(out_of_range ex) {
            cout << "Exception: " << ex.what() << endl;
            cout << "Exception type: class out_of_range" << endl;
        }
        catch(logic_error ex) {
            cout << "Exception: " << ex.what() << endl;
            cout << "Exception type: class logic_error" << endl;
        }
        catch(int ex) {
            cout << "Exception: " << ex << endl;
            cout << "Exception type: int" << endl;
        }
        catch(runtime_error ex) {
            cout << "Exception: " << ex.what() << endl;
            cout << "Exception type: class runtime_error" << endl;
        }
    }
    return 0;
}

总结:

抛出异常时,记得先捕获子类,再到父类,以免发生冲突

阅读更多
换一批

没有更多推荐了,返回首页