考虑以下代码:
class A
{
public:
virtual void f() throw ( int ) { }
};
class B: public A
{
public:
void f() throw ( int, double ) { }
};
编译时,它说派生类 B 与 A 相比具有更宽松的抛出说明符。这有什么重要性?如果我们尝试交换它们的异常规范,使得 A::f() 抛出 int 和 double 而 B::f() 只抛出 int,则不会出现错误。
考虑以下代码:
class A
{
public:
virtual void f() throw ( int ) { }
};
class B: public A
{
public:
void f() throw ( int, double ) { }
};
编译时,它说派生类 B 与 A 相比具有更宽松的抛出说明符。这有什么重要性?如果我们尝试交换它们的异常规范,使得 A::f() 抛出 int 和 double 而 B::f() 只抛出 int,则不会出现错误。
扩展第 2 点:A的调用者期望它只会int出现,但是如果你使用 a B(因为它是公开派生自A,也意味着它可以用作 a A),突然double也可以出现,这会破坏A's contract (只会int被抛出)。
您的 B 违反了 Liskov 替换原则 - 例如:
void foo(A* a) throw() // 即我不会抛出
{
尝试
{
a->f();
}
捕捉(整数)
{}
}
根据 A 的接口这是有效的;特别是,我们预计不会抛出 double。但是考虑一下如果我们打电话给
富(新B)
使用您描述的界面,以及
B::f()被扔双。