【问题标题】:Correct way to inherit from std::exception从 std::exception 继承的正确方法
【发布时间】:2011-12-30 11:08:00
【问题描述】:

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

throw My_Exception("Something bad happened.");

【问题讨论】:

  • 我知道这不能回答您的问题,但您可能想在开始使用异常之前阅读this。这里还有很多关于堆栈溢出的问题,关于异常是好是坏(答案大多是坏的)。
  • stackoverflow.com/q/1669514/52074 非常相似(几乎看起来像重复)并且有更多的支持。仅供参考,这个问题和链接都有相同的解决方案。
  • 这个有一个更好的答案 IMO。 obmarg 位于顶部,Johannes 始终位于底部。

标签: c++ exception


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    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() noexcept {}
    
        /** 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 noexcept {
           return msg_.c_str();
        }
    
    protected:
        /** Error message.
         */
        std::string msg_;
    };
    

    【讨论】:

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

    这个怎么样:

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

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

    【讨论】:

    • @user472155 +1 以获得好的答案。顺便说一句,我认为这里值得一提的是,您在示例中为 what 函数提供的签名仅暗示 C++11 之前的代码。
    • @Guy Avraham:你的意思是在 C++11 之后 virtual 关键字应该变成 override,还是别的什么?
    • @gg99 - 好点。我的意思是,从 C++11 开始,what 函数的签名变成了以下内容:virtual const char* what() const noexcept(注意在末尾添加了 noexcept 关键字)。另请参阅:en.cppreference.com/w/cpp/error/exception/what
    【解决方案4】:

    如果您的目标是创建一个异常以便不抛出通用异常 (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 };
    }
    

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

    为了避免您可以使用标题&lt;stdexcept&gt; 中预定义的任何便利类。请参阅这些“Exception categories”以获得灵感。

    【讨论】:

    • 查看en.cppreference.com/w/cpp/error/exception/exception std::exception 没有将字符串作为参数的构造函数。所以你的代码格式不正确。
    • @Kilian 我正在使用应该是常见且实用的实现特定行为。感谢您的提示,我会将其包含在答案中。
    【解决方案5】:

    what 方法是虚拟的,意思是你应该重写它来返回你想要返回的任何消息。

    【讨论】:

      【解决方案6】:

      这是一个例子

       class CommunicationError: public std::exception {
        public:
         explicit CommunicationError(const char* message) : msg(message) {}
         CommunicationError(CommunicationError const&) noexcept = default;
      
         CommunicationError& operator=(CommunicationError const&) noexcept = default;
        ~CommunicationError() override = default;
      
        const char* what() const noexcept override { return msg; }
       private:
        const char* msg;
      };
      

      [1]https://www.autosar.org/fileadmin/user_upload/standards/adaptive/17-03/AUTOSAR_RS_CPP14Guidelines.pdf

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-12
        • 2012-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-03
        • 1970-01-01
        相关资源
        最近更新 更多