Consider the following code:
class A
{
public:
virtual void f() throw ( int ) { }
};
class B: public A
{
public:
void f() throw ( int, double ) { }
};
When compiled, it says that derived class B has a looser throw specifier compared to A. What is the importance of this? If we try to exchange their exception specification, such that A::f() throws int and double while B::f() throws only int, the error does not ap开发者_运维技巧pear.
- Don't use exception specifications in C++. It's very counter-intuitive compared to, say, Java's ones.
- Having a wider specification in the derived class breaks LSP (Liskov Substitution Principle).
To expand on point 2: A
's callers expect that only int
comes out, but if you use a B
(which, because it's publicly derived from A
, also means it's usable as an A
), suddenly double
can come out too, and that would break A
's contract (that only int
gets thrown).
Your B violates the Liskov Substitution Principle - eg:
void foo(A* a) throw() // ie I will not throw { try { a->f(); } catch(int) {} }
This is valid according to the interface for A; in particular, we do not expect a double to be thrown. But consider if we were to call
foo(new B)
with the interface you describe, and
B::f()were to throw a double.
精彩评论