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

问题:

原代码:

//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;
}

总结:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值