25

This might be kind of a silly question, but in C++, when I want to throw an exception.. what do I throw?

Am I supposed to throw std::exception, or is that reserved by the standard library? Or should I throw a string or int? Or should I just throw whatever I feel is appropriate?

Agnel Kurian
  • 57,975
  • 43
  • 146
  • 217
  • 3
    Don't throw strings or ints! If you always throw subclasses of `std::exception`, you can put a catch-all clause in `main` that handles all exceptions not handled elsewhere and prints the `what()` of the exception. – Fred Foo Feb 27 '12 at 21:03

5 Answers5

32

Throw a class that's derived from std::exception; if you #include <stdexcept>, you can pick from a number of ready-made, useful derived classes.

Deriving from std::exception allows your handlers to follow a recognizable style, as you can always use .what() to get a textual message. Don't throw primitive types, since they carry no semantic information.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 10
    I would counter (though practically the same) that in most cases people should derive their exceptions from std::runtime_error (which itself happens to be derived from std::exception) – Martin York Feb 27 '12 at 21:19
8

Generally people don't throw std::exception directly for the simple reason that it doesn't store any error messages. There wouldn't be anything for the what method to return. I get confused sometimes over this because MSVC provides a non-standard extension to this a parameterized constructor in std::exception that accepts a string.

You can choose among existing exception classes like std::runtime_exception or define your own. This is somewhat subjective but I recommend keeping the number of exception classes to a minimum as RAII can eliminate a lot of the need to have multiple code branches and catch blocks for different exception types. Often the message combined with RAII-conforming code is enough to gracefully recover from any exception.

And finally, I recommend all exceptions you throw inherit from std::exception for similar reasons. You don't want to have to litter your code with many different catch blocks for different exception types if you can avoid it. Solve the problem as generally as you can.

stinky472
  • 6,737
  • 28
  • 27
2

The primary exception to throwing something derived from std::exception would be if you're using some framework (e.g., MFC) with its own exception hierarchy. In that case, you generally want to derive from an appropriate spot in their hierarchy instead.

Note that I'm not particularly attempting to hold MFC up as an example of clean exception handling (or clean design in general), only an example of a framework that includes an exception hierarchy. When you're using a framework that already defines an exception hierarchy, you're generally better off using it.

In other words, unlike the preference in C++ otherwise, it's generally accepted that exceptions should be a single, monolithic hierarchy with a single root. For the standard library, that single root is std::exception, but other frameworks have alternatives, and if they provide one you generally want to fit yours into it.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

Unlike java you CAN throw whatever (int, string, MyClass, ...) you want. But listen to Kerrek. :)

Kashyap
  • 15,354
  • 13
  • 64
  • 103
0

Usually you'll want to throw one of the exceptions derived from std::exception as others have said.

On occasion I've thrown other types, but only if it's caught within the same block and the value is something useful in that context.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • If you're catching "within the same block", you probably shouldn't be throwing an exception in the first place. Exceptions are for exceptional conditions, but if you can handle the condition right there, then it sounds like it's just part of the normal program flow. (And don't forget that *throwing* an exception can be a lot more expensive than just checking a some local state.) – Kerrek SB Feb 27 '12 at 21:23
  • @KerrekSB, I can't remember the exact circumstances where I did this, but I'm sure it was an exceptional condition that wasn't part of the *normal* flow. Probably also deeply nested where alternative approaches would have been uglier. – Mark Ransom Feb 27 '12 at 21:28
  • 2
    Fair enough. There *are* situations where an exception can make a complicated algorithm clearer and easier to understand... – Kerrek SB Feb 27 '12 at 21:30