I saw the following snippet code:
class Foo
{
public:
void virtual func() throw (int, float) = 0;
};
class Bar : public Foo
{
public:
void virtual func() throw(short); // line 1: compile error "
// looser throw specifier"
void virtual func() throw(); // line 2: can compile
void virtual func() throw(float, int); // line 3: can compile
void virtual func() throw(float); // line 4: can compile
void virtual func() throw(int); // line 5: can compile
};
int main(void)
{
return 1;
}
Q1> What is meaning of
void virtual func() throw (int, float) = 0;
Q2> why line1 cannot pass the compiler?
Thank you
Let’s break this down. The declaration:
has 2 constructs that you’re asking about. the
=0construct tells the compiler that the declared function is ‘abstract’, which tells the compiler that the function need not be defined in theclass Foo(though it can be – but it usually isn’t) and that an object ofclass Foocannot be directly created – either as a local, global or vianew. However, you can have pointers or references to objects ofclass Foo. Some derived class needs to override the function as a non-abstract function – objects of that class can be directly created (as long as there are no other abstract functions that haven’t been made ‘concrete’).The
throw (int, float)construct is an exception specifification. This tells the compiler that the function’s contract is that it will only throw exceptions of typeintorfloatif it throws an exception. If the function throws some other kind of exception, the compiler is obligated to handle that specially (by callingstd::unexpected()).Now, if you try to override that function in a derived class with the following declaration:
You’re saying that the function’s contract is that it will throw exceptions of type
shortif an exception is thrown. However, throwingshortis not part of the contract of the function being overridden, so the compiler doesn’t permit it.If you declare the override like so:
You’re saying that the override can throw a
float, which is part of the contract of the original declaration (if it never throws anintthat doesn’t break the contract – the original contract only says that the function is allowed to throw anint, not that it has to).The relevant part of the standard is 15.4/3 Exception specifications:
Note that the standard explicitly states that an exception specification is not part of the function’s type (15.4/12), so a function pointer can, for example, point to functions that have different exception specifications.