问题:
原代码:
//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;
}
总结:
抛出异常时,记得先捕获子类,再到父类,以免发生冲突