正确的继承std :: exception的方法

sma*_*llB 53 c++ exception

我刚刚创建了异常层次结构,并希望传递char*给我的一个派生类的构造函数,并带有一条告诉错误的消息,但显然std::exception没有允许我这样做的构造函数.然而,有一个类成员被称为what()可以传递一些信息.
我怎么能(我可以?)将文本传递给a的派生类,std::exception以便通过我的异常类传递信息,所以我可以在代码中的某处说:

throw My_Exception("Something bad happened.");
Run Code Online (Sandbox Code Playgroud)

tun*_*2fs 62

我使用以下类作为我的异常,它工作正常:

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_;
};
Run Code Online (Sandbox Code Playgroud)

  • @Water这段代码与`std :: runtime_error`相同.无需重新发明轮子. (11认同)
  • 我不认为这是一个好主意。构造 std::string 会抛出异常,这将导致调用终止。 (11认同)
  • 我同意@DDrmmr 的说法,即您正在重新发明轮子(即您正在重新实现`std::runtime_error` 或`std::logic_error`)。 (3认同)
  • msg_ 是 Exception 的 **protected** 成员;它是 std::string 的一个实例,因此它可以访问它的 .c_str 成员函数(转换为 c 字符串)。 (2认同)
  • 复制构造函数呢? (2认同)

obm*_*arg 55

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

然后,它只是从新的继承类调用runtime_error/logic_error构造函数的情况,或者如果您使用的是c ++ 11,则可以使用构造函数继承.


小智 8

这个怎么样:

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

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

  • @ user472155 +1为好的答案.顺便说一下,我认为值得一提的是,您在示例中为what函数提供的签名仅表示在C++ 11之前的代码. (2认同)
  • @gg99 - 好点。我的意思是,从 C++11 开始,`what` 函数的签名变成了以下内容:`virtual const char* what() const noexcept`(注意最后添加了 `noexcept` 关键字)。另请参见此处:https://en.cppreference.com/w/cpp/error/exception/what (2认同)

Joh*_*nes 6

如果您的目标是创建一个异常,以免引发一般性异常(cpp:S112),则可能只想使用using声明公开从(C ++ 11)继承的异常。

这是一个最小的示例:

#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 };
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 看看 https://en.cppreference.com/w/cpp/error/exception/exception std::exception 没有将字符串作为参数的构造函数。所以你的代码格式不正确。 (2认同)

Som*_*ude 5

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