I heard you should never throw a string because there is a lack of information and you\'ll catch exceptions you dont expect to catch. What are good practice for throwing exc
In my opinion, a function should throw an exception if it can't keep its "promise", if it has to break its "contract". The function's signature (name and parameters) determine its contract.
Given these two member functions:
const Apple* FindApple(const wchar_t* name) const;
const Apple& GetApple(const wchar_t* name) const;
The names of these functions as well as their return values indicate to me that in the case of FindApple the function is perfectly capable of returning NULL when the correct apple was not found, but in the case of GetApple you're expecting an apple to return. If that second function can't keep its promise, it must throw an exception.
Exceptions are meant for those exceptional conditions in which a function has no other way of reporting these conditions. If you decide to make it a part of the promise (read: function signature) then it can report that condition without throwing an exception.
Note that in the case of FindApple, it's up to the caller to decide how to handle the condition of "not finding the right apple" because it's no longer an exceptional condition.
You might be tempted to try to avoid all exceptions, but that means you have to account for all possible exceptional conditions, and you're placing the burden on the caller instead. The caller needs to check for "error conditions" then.
Ultimately, an exception needs to be handled, but only by the caller that knows how to handle a particular condition in a useful way. And I mean this in the widest possible interpretation: a service that gives up will try again later, a UI that provides a helpful error message, a web app that presents a "oops" screen but that recovers nicely, ... and so on.
Dave
You should always throw an exception class derived from std::exception. This allows a certain consistency to your interface and allows more flexibility to the clients of these methods or functions. For example if you want to add a catch all handler you may be able to add a
catch(std::exception& e)block and be done with it. (Though often you won't be able to get away with that if you don't control all the code that can throw).
I tend to throw only exceptions provided by the the standard (i.e. std::runtime_error) but if you want to provide extra granularity to your handlers, you should feel free to derive your own from std::exception. See the C++ FAQ lite.
Also, you should throw a temporary and catch it by reference (to avoid the copy ctor be invoked at your catch site). Throwing pointers is also frowned upon since it is unclear who should clean up the memory. C++ FAQ Lite deals with this too.
From the C++ FAQ, [17.12] What should I throw?:
Generally, it's best to throw objects, not built-ins. If possible, you should throw instances of classes that derive (ultimately) from the
std::exception
class.
...and
The most common practice is to throw a temporary: (see example that follows)
Here is a simple example of throwing an exception that takes barely any resources:
class DivisionError {};
class Division
{
public:
float Divide(float x, float y) throw(DivisionError)
{
float result = 0;
if(y != 0)
result = x/y;
else
throw DivisionError();
return result;
}
};
int main()
{
Division d;
try
{
d.Divide(10,0);
}
catch(DivisionError)
{
/*...error handling...*/
}
}
The empty class that is thrown does not take any resource or very few...
For a current project, we thought about the appropriate action that could be taken by the main program loop. The basic program accepts XML messages, and saves the information into a database (with a fair amount of processing in between).
The first item is a checked exception, since we considered data checking to be part of a method's interface. The others are unchecked since the main loop cannot know the implementations of subcomponents, e.g. an implementation may use an SQL database, or may simply persist data in memory -- the caller doesn't need to know.
As it has been already said use them for exceptional situations only.
Always provide a way for the user to avoid throwing an exception, eg. if you have method, that will throw if something goes wrong like this:
public void DoSomethingWithFile() {
if(!File.Exists(..))
throw new FileNotFoundException();
}
Provide another method for the user to call:
public bool CanDoSomething() {
return File.Exists(..);
}
This way there the caller can avoid exceptions if he wants. Do not hesitate to throw if something is wrong - "fail fast", but always provide exception-free path.
Also keep your exception class hierarchy flat and take a look at the standard exceptions like InvalidStateException and ArgumentNullExcpetion.