【问题标题】:Exception class with a char* constructor带有 char* 构造函数的异常类
【发布时间】:2015-04-22 19:33:48
【问题描述】:

我在VS2008上遇到了如下代码

if (!CreateProcess( NULL,
                    const_cast<LPWSTR>(ss.str().c_str()),
                    NULL,
                    NULL,
                    FALSE,
                    CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS,
                    NULL,
                    NULL,
                    &si,
                    &pi))
{
    throw   std::exception("Unable to format Device");
}

现在我将代码移植到 mingw gcc 并收到错误

error: no matching function for call to 'std::exception::exception(const char [23])'

调查这个问题我注意到 Visual Studio 有一个文件异常,它确实有一个异常类并且确实接受了 char*。有些定义是这样的

   __CLR_OR_THIS_CALL exception();
    __CLR_OR_THIS_CALL exception(const char *const&);
    __CLR_OR_THIS_CALL exception(const char *const&, int);
    __CLR_OR_THIS_CALL exception(const exception&);
    exception& __CLR_OR_THIS_CALL operator=(const exception&);
    virtual __CLR_OR_THIS_CALL ~exception();
    virtual const char * __CLR_OR_THIS_CALL what() const;

我的问题是我应该如何在 mingw gcc 上规避这个构建问题?我应该创建一个继承自 std::runtime_error 的新类并抛出它吗?

【问题讨论】:

标签: c++ visual-studio c++11 gcc


【解决方案1】:

意见在这里发挥作用。问题是std::exception 没有接受字符串参数的构造函数;这是一个 MSVC 扩展。我看到了两种解决方法:

  1. 不要传递字符串参数
  2. 不要使用std::exception

第一种情况很简单;只需使用

throw std::exception();

缺点是您不会收到描述性错误消息。

如果错误消息很重要,则不能直接使用std::exception。在这种情况下,您可以使用 std::logic_errorstd::runtime_error,它们继承 std::exception 并且确实有构造函数采用字符串参数,所以

throw std::runtime_error("Unable to format Device");

可能已经解决了问题。捕获std::exceptioncatch 子句也将捕获std::runtime_error。但是有一个潜在的问题:捕获std::runtime_errorcatch 子句不会捕获std::exception,但会捕获这个。

这似乎有点极端,完全有可能对您来说不是问题。但是,如果有可能沿着调用堆栈有一个 catch 子句捕获 std::runtime_error 但不应捕获此代码引发的异常,您可以从 std::exception 派生您自己的异常类,这确实需要一个字符串参数。因为这个类是新的,它不会被现有的catch 子句捕获。例如:

class descriptive_exception : public std::exception {
public:
  descriptive_exception(std::string const &message) : msg_(message) { }
  virtual char const *what() const noexcept { return msg_.c_str(); }

private:
  std::string msg_;
}

然后

throw descriptive_exception("Unable to format Device");

这可以说不是很漂亮,也不太可能是必需的,因此更可能的解决方案是使用std::runtime_errorstd::logic_error(或从其中一个派生的类)。

std::logic_error还是std::runtime_error哪个更合适不是很明确;在这种情况下,我可能会选择std::runtime_error,因为该错误在理论上似乎无法预测,但鉴于std::domain_errorstd::future_error 派生自std::logic_error,它在该层次结构中不会完全不合适。我认为这是一个见仁见智的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    • 2012-04-14
    • 2013-11-10
    • 2011-10-10
    相关资源
    最近更新 更多