Skip to main content
Code Review

Return to Answer

Commonmark migration
Source Link

##Creating your Own exceptions

Creating your Own exceptions

##Creating your Own exceptions

Creating your Own exceptions

added 673 characters in body
Source Link
Loki Astari
  • 97.7k
  • 5
  • 126
  • 341

##Creating your Own exceptions

I used to create exceptions for different situations but found I never used them. So I have started simply using std::runtime_error. The only time I define a specific exception is when it can be usefully caught outside the library layer I am throwing from.

The trouble is the definition of "usefully caught". This not only means that the exception needs to carry information that I can use to fix the problem but the library itself must provide a public API that will allow me to fix the situation.

If all you can do with the exception is log it (including dump to std::cout). Then is it really a useful exception to catch?

##Creating your Own exceptions

I used to create exceptions for different situations but found I never used them. So I have started simply using std::runtime_error. The only time I define a specific exception is when it can be usefully caught outside the library layer I am throwing from.

The trouble is the definition of "usefully caught". This not only means that the exception needs to carry information that I can use to fix the problem but the library itself must provide a public API that will allow me to fix the situation.

If all you can do with the exception is log it (including dump to std::cout). Then is it really a useful exception to catch?

Source Link
Loki Astari
  • 97.7k
  • 5
  • 126
  • 341

You should probably inherit from std::runtime_error rather than std::exception.

The std::exception and all its descendants already implement what() so there is no need to implement that in your code. So you can remove these:

 // Returns member_err.
 virtual const char* what() const throw();
 protected:
 // A description of the error. Should probably set this to private.
 const char* member_err;

There is no need for a virtual destructor. That is already taken care of in the base class std::exception. Since you are not doing memory management (your example shows string literals) these methods are empty anyway. So you can remove this:

 virtual ~LibException() throw ();
 virtual ~ProcessException() throw ();

This seems obtuse:

 // Returns a char* pointer to the reason.
 //
 // E.g. NETWORK = "NETWORK"
 // @return: <const char*> member_reason.
 const char* getReasonChar() const throw();

Why not just return Reason?

I personally don't like interfaces that take pointers. There is no ownership semantics associated with the pointer and thus people can mistakenly provide the wrong type of pointer (ie a dynamically allocated one in this case). So I would change the interface to be std::string const& this guarantees the correct semantics are used (and you can still use the string literal). This also jibes with the std::exception (and family) which all accept a std::string for the constructor.

LibException(std::string const& err);

Edit: Moreover I have another exception class called ParseException (very similar to the derived class above) which is thrown when a parser that is parsing a file or a command from the shell fails unexpectedly.

I think the key phrase here is fails unexpectedly. If its unexpected to fail for this reason then its an exception.

I have read that such errors are better handled via assert statements because they don't represent "exceptional" cases.

Asserts are the worst type of control and they are really only good for debugging; not for error handling. Remember assert() compiles to the NO-OP when in release mode so there is no checks.

Could anyone please comment on this?

Control flow is usually not best handled with exceptions. But everything is situational. If you find it useful feature to use then go ahead.

lang-cpp

AltStyle によって変換されたページ (->オリジナル) /