tags:

views:

398

answers:

4

Question 1:

Is is possible to throw an exception that will not be caught by std::exception?

try
{
}
catch(std::exception & e)
{
}
catch(...)
{
  //Is this block needed?
}

Question 2:

Is it better to have:

catch(std::exception & e)

Or

catch(std::exception e)

Or

catch(const std::exception &e)//<--- this is the method I usually use
+6  A: 

It sure is, you can throw any type you want, and it doesn't need to be derived from std::exception.

Catching a const reference is better. The reason is that you can throw a const or a non-const, and it can be caught by a non-const. Which works like a silent casting away of const.

Daniel Earwicker
For example, "throw 1;" is legal.
ChrisW
I love 'throw "Fnugle not found"' for test code.
peterchen
Could you give me an example of why it's better to catch with const? A dangerous situation where you catch with std::exception e instead?
Net Citizen
An example of why it's better to catch with const is that the thrower might throw a const static instance of something, expecting that the catcher will not modify it.
ChrisW
Following up ChrisW, throwing an exception doesn't have to end the program so if you modified that static const object you would negatively impact the semantics of the next time that exception occurred.
jmucchiello
+8  A: 

Q1: yes. you can throw any type, not necessary types that inherit from std::exception.
you can write throw 1; to throw and int or throw "hello"; to throw a char*, both of which do not inherit from std::exception. this is however considered bad practice because the user of the class can't expect you to throw anything. If you don't want to inherit from std::exception what you usually do is create your own exception hierarchy.

Q2: catching an exception by value (2nd option) is a bad practice because you force the exception instance to be copied and in that possibly performing allocations which may cause further exceptions.
Using the first option suggest you intend to change e in the catch block which is also something you'd probably like to avoid because exceptions are usually maintained immutable after creation. The only thing that is left is the third option.

shoosh
"The only thing that is left is the third option" -- Another option, but not a really good option, is to throw and catch by pointer.
ChrisW
@ChrisW: even if Microsoft has made it a common option through COM, in general, throwing and catching by pointer is not recommended. http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.6
David Rodríguez - dribeas
@dribeas - COM does exceptions a completely different way; however, MS did design their MFC library to throw/catch pointers. This was because when they first tried to implement it, their C++ compiler didn't support exceptions! So it was just macros over setjmp/longjmp, with no stack unwinding... awesomely half-baked.
Daniel Earwicker
In an MS environment you also have structured exceptions _SEH which use another mechanism entirely.
Greg Domjan
"throw by pointer" is really actually "throw by value" because you throw a pointer and the pointer is copied.
shoosh
+3  A: 

The answer to your second question is that you should throw by value and catch by reference. If you catch by value you may get 'object slicing'.

ChrisW
Plus the inconvenience of possibly triggering other exceptions during the copy (copy of the exception internal data, allocation of internal buffers --consider a message string)
David Rodríguez - dribeas
A: 

It is sometimes necessary to throw an exception that does not inherit from std::exception. When shipping a shared library it's best practice to either re-implement or wrap most the std library types instead of exposing methods/functions that use them directly as it can cause all sorts of linker/compiler interoperability issues.

MrEvil