tags:

views:

209

answers:

4
/* user-defined exception class derived from a standard class for exceptions*/

class MyProblem : public std::exception {

public:

    ...

    MyProblem(...) { //special constructor
    }

    virtual const char* what() const throw() {
    //what() function
    ...
    }

};

...

void f() {
...

//create an exception object and throw it

throw MyProblem(...);

...


}

My question is why there is a "const throw()" after what()? Normally,if there is a throw() , it implies that the function before throw() can throw exception.However ,why there is a throw here?

+8  A: 

Empty braces in "throw()" means the function does not throw.

Alex B
Should not throw You hope.
Martin York
Perhaps, "is not supposed to throw" then.
Alex B
It might be better to phrase it as: "An exception will not be propagated outside of that function". Your program might "terminate" if an exception is thrown from within that function, but it won't be propagated.
Richard Corden
+6  A: 

Empty parentheses in throw() are sometimes said to mean the function does not throw. If C++ were a bit more like Java, this might be the case.

Empty parens in throw() actually mean that the compiler should emit code at every call site to prevent any exception thrown by the function from propagating past the call site. So the function might still throw (there's no way to stop it - unlike Java, the throw specification in C++ is not part of the function signature, so there's no way to prevent you linking against a version of the function that does throw something). But the call to the function doesn't.

So the code surrounding that call can assume that it doesn't throw anything, because the compiler ensures at run time, by emitting code, that anything it throws is trapped and std::unexpected() called instead of propagating the exception. This usually results in program termination.

Except when it doesn't. MSVC at versions 7 and below doesn't actually bother emitting the extra code, but it does still make optimizations based on the assumption that nothing is thrown.

So, an empty throw specification allows optimizations on MSVC 7 or less. If the function actually does throw after all, then something unpleasant will happen. On other compilers, it may allow optimizations based on nothing being propagated, but at the cost of emitting extra try/catch blocks to enforce that if anything is thrown, then it's handled (probably by terminating) instead of propagating it.

This situation is rather different from Java, where (Errors and RuntimeExceptions not included) a throws clause means business, and the compiler will enforce by compile time checking that no disallowed exceptions are thrown. C++ has no such compile time checking.

Herb Sutter has more to say on the topic: http://www.gotw.ca/publications/mill22.htm

Steve Jessop
+3  A: 

The const qualifies the function what(), saying it does not modify the internal structure of the exception object.

The throw() means it doesn't throw an exception, either - as noted by OneByOne and Checkers.

The two words are largely unrelated, even though they appear right next to each other in the signature.

Jonathan Leffler
+4  A: 

The const is a separate issue to throw().
This indicates that this is a const method. Thus a call to this method will not change the state of the object.

The throw() means the method will not throw any exceptions.

To the USER of this method, the method will only return through normal means and you do not need to worry about the call generating exceptions.

To the IMPLEMENTER of the method there is more to worry about.
Unlike Java this is not a compile time constraint but a runtime constraint. If the implementer writes the function so that it accidentally throws an exception out of the method then the runtime will stop the application dead (no unwinding of the stack no destructors etc).

But the convention is that the implementer will take the extra precautions to catch all internal exceptions.

PS
You may want to derive from std::runtime_error

(From [email protected]): Not quite.
The no throw specifier is actively used. It is an indication of exception safety demonstrates that the method provides the no throw guarantee

On the other hand the other exception specifiers are not used because they are too dangerous. If you get them wrong it causes an application termination via (std::unexpected). The default action is application termination without unwinding the stack and without cleaning up using object destructors. In MHOP this is hardly ever desirable.

Martin York
"the convention is..." Which is why most folks say not to bother with throw specifiers in C++. If the implementer catches the exceptions, then there's no point telling the calling code to catch them too. If the implementer does throw something, then at best something std::unexpected will happen...
Steve Jessop
@onebyone.livejournal.com: Answered in line
Martin York