带有char*构造函数的异常类

Jam*_*nco 14 c++ gcc visual-studio c++11

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

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

error: no matching function for call to 'std::exception::exception(const char [23])'
Run Code Online (Sandbox Code Playgroud)

调查问题我注意到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;
Run Code Online (Sandbox Code Playgroud)

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

Win*_*ute 46

意见在这里发挥作用.问题是std::exception没有一个带字符串参数的构造函数; 这是MSVC扩展.我认为有两种方法可以解决这个问题:

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

第一种情况很简单; 只是用

throw std::exception();
Run Code Online (Sandbox Code Playgroud)

缺点是您没有收到描述性错误消息.

如果错误消息很重要,std::exception则不能直接使用.在这种情况下,你可以使用两种std::logic_error或者std::runtime_error,它继承std::exception并做有构造函数取一个字符串参数,所以

throw std::runtime_error("Unable to format Device");
Run Code Online (Sandbox Code Playgroud)

可能已经解决了这个问题.catch抓住std::exception遗嘱的条款也抓住了std::runtime_error.但是有一个潜在的问题:catch捕获的条款std::runtime_error不会捕获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_;
}
Run Code Online (Sandbox Code Playgroud)

然后

throw descriptive_exception("Unable to format Device");
Run Code Online (Sandbox Code Playgroud)

这可能不是很漂亮,并且它不太可能是必要的,因此更可能的解决方案是使用std::runtime_errorstd::logic_error(或从其中一个派生的类).

是否std::logic_errorstd::runtime_error更合适不是很明确; 在这种情况下,我可能会选择,std::runtime_error因为错误在理论上似乎不可预测,但考虑到std::domain_error并且std::future_error从中得出std::logic_error,它在该层次结构中并不完全不合适.我认为这是一个意见问题.