如果基类和子类都被做为异常捕获,则子类的catch代码块必须出现在基类之前。
如果把基类放在前面,则子类的catch代码块永远都不会被调用。
例如,下面程序打印“Caught Base Exception”。
- #include<iostream>
- using namespace std;
- class Base {};
- class Derived: public Base {};
- int main()
- {
- Derived d;
- try {
- throw d;
- }
- catch(Base b) {
- cout<<"Caught Base Exception";
- }
- catch(Derived d) {
- cout<<"Caught Derived Exception";
- }
- return 0;
- }
上述程序中,用引用也不行。因为catch对象是静态类型,而catch对象所引用的异常对象是动态类型,跟动态绑定一样,必须使用指针或引用才可以
上述程序中,如果调整下声明的顺序,则都可以被捕获。
下面是修改之后的程序,会打印“Caught Derived Exception”。
- #include<iostream>
- using namespace std;
-
- class Base {};
- class Derived: public Base {};
- int main()
- {
- Derived d;
-
- try {
- throw d;
- }
- catch(Derived d) {
- cout<<"Caught Derived Exception";
- }
- catch(Base b) {
- cout<<"Caught Base Exception";
- }
- return 0;
- }
Java中, 编译器不允许在子类之前捕获基类的异常。C++中,编译器会给出类似下面的警告,但是还是可以编译成功。
visual studio 2015会提示: "warning C4286: “Derived”: 由基类(“Base”)在行 17 上捕获"
例如,下面Java代码会编译失败, “exception Derived has already been caught”
-
- class Base extends Exception {}
- class Derived extends Base {}
- public class Main {
- public static void main(String args[]) {
- try {
- throw new Derived();
- }
- catch(Base b) {}
- catch(Derived d) {}
- }
- }
注:此情况还适用于const和非const ,数组和引用的情况,详见《c++ primer》P584.