C++ 从 std::exception 继承的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8152720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:05:20  来源:igfitidea点击:

Correct way to inherit from std::exception

c++exception

提问by smallB

I've just created exception hierarchy and wanted to pass char*to constructor of one of my derived classes with a message telling what's wrong, but apparently std::exceptiondoesn't have constructor which would allow me to do so. Yet there is a class member called what()which would suggest that some information can be passed.
How can I (can I?) pass text to derived class of a std::exceptionin order to pass info with my exception class, so I can say somewhere in the code:

我刚刚创建了异常层次结构,并想通过char*一条消息传递给我的派生类之一的构造函数,告诉我出了什么问题,但显然std::exception没有构造函数可以让我这样做。然而,有一个名为的班级成员what()暗示可以传递一些信息。
我如何(我可以?)将文本传递给 a 的派生类,std::exception以便通过我的异常类传递信息,所以我可以在代码中的某处说:

throw My_Exception("Something bad happened.");

回答by tune2fs

I use the following class for my exceptions and it works fine:

我将以下类用于我的异常并且它工作正常:

class Exception: public std::exception
{
public:
    /** Constructor (C strings).
     *  @param message C-style string error message.
     *                 The string contents are copied upon construction.
     *                 Hence, responsibility for deleting the char* lies
     *                 with the caller. 
     */
    explicit Exception(const char* message):
      msg_(message)
      {
      }

    /** Constructor (C++ STL strings).
     *  @param message The error message.
     */
    explicit Exception(const std::string& message):
      msg_(message)
      {}

    /** Destructor.
     * Virtual to allow for subclassing.
     */
    virtual ~Exception() throw (){}

    /** Returns a pointer to the (constant) error description.
     *  @return A pointer to a const char*. The underlying memory
     *          is in posession of the Exception object. Callers must
     *          not attempt to free the memory.
     */
    virtual const char* what() const throw (){
       return msg_.c_str();
    }

protected:
    /** Error message.
     */
    std::string msg_;
};

回答by obmarg

If you want to make use of the string constructor, you should inherit from std::runtime_erroror std::logic_error which implements a string constructor and implements the std::exception::what method.

如果你想使用字符串构造函数,你应该从std::runtime_errorstd::logic_error继承,它实现了一个字符串构造函数并实现了 std::exception::what 方法。

Then it's just a case of calling the runtime_error/logic_error constructor from your new inherited class, or if you're using c++11 you can use constructor inheritance.

那么这只是从新继承的类中调用 runtime_error/logic_error 构造函数的一种情况,或者如果您使用的是 c++11,则可以使用构造函数继承。

回答by smallB

How about this:

这个怎么样:

class My_Exception : public std::exception
{
public:
virtual char const * what() const { return "Something bad happend."; }
};

Or, create a constructor accepting the description if you like...

或者,如果您愿意,可以创建一个接受描述的构造函数...

回答by Johannes

If your goal is to create an exception so that you do not throw a generic exception (cpp:S112) you may just want to expose the exception you inherit from (C++11) with a using declaration.

如果您的目标是创建一个异常,以便不抛出通用异常 ( cpp:S112),您可能只想使用 using 声明公开从 ( C++11)继承的异常。

Here is a minimal example for that:

这是一个最小的例子:

#include <exception>
#include <iostream>

struct myException : std::exception
{
    using std::exception::exception;
};

int main(int, char*[])
{
    try
    {
        throw myException{ "Something Happened" };
    }
    catch (myException &e)
    {
        std::cout << e.what() << std::endl;
    }
    return{ 0 };
}

As Kilian points out in the comment section the example depends on a specific implementation of std::exception that offers more constructors than are mentioned here.

正如 Kilian 在评论部分指出的那样,该示例取决于 std::exception 的特定实现,该实现提供了比此处提到的更多的构造函数。

In order to avoid that you can use any of the convenience classes predefined in the header <stdexcept>. See these "Exception categories" for inspiration.

为了避免这种情况,您可以使用标题中预定义的任何便利类<stdexcept>。请参阅这些“异常类别”以获取灵感。

回答by Some programmer dude

The whatmethod is virtual, and the meaning is that you should override it to return whatever message you want to return.

what方法是虚拟的,意思是您应该覆盖它以返回您想要返回的任何消息。