Should I inherit from std::exception?

前端 未结 14 1437
有刺的猬
有刺的猬 2020-11-30 18:56

I\'ve seen at least one reliable source (a C++ class I took) recommend that application-specific exception classes in C++ should inherit from std::exception. I\

相关标签:
14条回答
  • 2020-11-30 19:40

    Yes you should derive from std::exception.

    Others have answered that std::exception has the problem that you can't pass a text message to it, however it is generally not a good idea to attempt to format a user message at the point of the throw. Instead, use the exception object to transport all relevant information to the catch site which can then format a user-friendly message.

    0 讨论(0)
  • 2020-11-30 19:41

    The reason why you might want to inherit from std::exception is because it allows you to throw an exception that is caught according to that class, ie:

    class myException : public std::exception { ... };
    try {
        ...
        throw myException();
    }
    catch (std::exception &theException) {
        ...
    }
    
    0 讨论(0)
  • 2020-11-30 19:41

    Since the language already throws std::exception, you need to catch it anyway to provide decent error reporting. You may as well use that same catch for all unexpected exceptions of your own. Also, almost any library that throws exceptions would derive them from std::exception.

    In other words, its either

    catch (...) {cout << "Unknown exception"; }
    

    or

    catch (const std::exception &e) { cout << "unexpected exception " << e.what();}
    

    And the second option is definitely better.

    0 讨论(0)
  • 2020-11-30 19:42

    There is one problem with inheritance that you should know about is object slicing. When you write throw e; a throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw. That could be not what you're expecting. Example of problem you could find here.

    It is not an argument against inheritance, it is just 'must know' info.

    0 讨论(0)
  • 2020-11-30 19:42

    Another reason to sub-class exceptions is a better design aspect when working on large encapsulated systems. You can reuse it for things such as validation messages, user queries, fatal controller errors and so on. Rather than rewriting or rehooking all of your validation like messages you can simply "catch" it on the main source file, but throw the error anywhere in your entire set of classes.

    e.g. A fatal exception will terminate the program, a validation error will only clear the stack and a user query will ask the end-user a question.

    Doing it this way also means you can reuse the same classes but on different interfaces. e.g. A windows application can use message box, a web service will show html and reporting system will log it and so on.

    0 讨论(0)
  • 2020-11-30 19:52

    Though this question is rather old and has already been answered plenty, I just want to add a note on how to do proper exception handling in C++11, since I am continually missing this in discussions about exceptions:

    Use std::nested_exception and std::throw_with_nested

    It is described on StackOverflow here and here, how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.

    Since you can do this with any derived exception class, you can add a lot of information to such a backtrace! You may also take a look at my MWE on GitHub, where a backtrace would look something like this:

    Library API: Exception caught in function 'api_function'
    Backtrace:
    ~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
    ~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
    

    You don't even need to subclass std::runtime_error in order to get plenty of information when an exception is thrown.

    The only benefit I see in subclassing (instead of just using std::runtime_error) is that your exception handler can catch your custom exception and do something special. For example:

    try
    {
      // something that may throw
    }
    catch( const MyException & ex )
    {
      // do something specialized with the
      // additional info inside MyException
    }
    catch( const std::exception & ex )
    {
      std::cerr << ex.what() << std::endl;
    }
    catch( ... )
    {
      std::cerr << "unknown exception!" << std::endl;
    }
    
    0 讨论(0)
提交回复
热议问题