带有 char* 构造函数的异常 class
Exception class with a char* constructor
我在 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 有一个文件异常,它确实有一个异常 class 并且确实接受了 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 的新 class 并将其抛出吗?
意见在这里很重要。问题是 std::exception
没有接受字符串参数的构造函数;这是一个 MSVC 扩展。我看到了两种解决方法:
- 不要传递字符串参数
- 不要使用
std::exception
第一种情况很简单;只需使用
throw std::exception();
缺点是您不会收到描述性错误消息。
如果错误消息很重要,直接使用 std::exception
不是一个选项。在这种情况下,您可以使用 std::logic_error
或 std::runtime_error
,它们继承 std::exception
并且构造函数采用字符串参数,因此
throw std::runtime_error("Unable to format Device");
可能已经解决了问题。 catch
捕获 std::exception
的子句也将捕获 std::runtime_error
。但是,有一个潜在的问题:catch
捕获 std::runtime_error
的子句不会捕获 std::exception
但会捕获这个。
这似乎是一个极端案例,完全有可能对您来说不是问题。但是,如果调用堆栈中有一个 catch
子句捕获 std::runtime_error
但不应该捕获此代码抛出的异常,则您可以派生自己的异常 class 来自 std::exception
确实需要一个字符串参数。因为 class 是新的,所以它不会被现有的 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_error
或 std::logic_error
(或派生自 class其中之一)。
std::logic_error
还是std::runtime_error
哪个更合适,不是很明确;在这种情况下,我可能会选择 std::runtime_error
,因为该错误似乎在理论上什至不可预测,但考虑到 std::domain_error
和 std::future_error
来自 std::logic_error
,它不会是在那个层次结构中完全不合适。这个我觉得见仁见智吧。
我在 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 有一个文件异常,它确实有一个异常 class 并且确实接受了 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 的新 class 并将其抛出吗?
意见在这里很重要。问题是 std::exception
没有接受字符串参数的构造函数;这是一个 MSVC 扩展。我看到了两种解决方法:
- 不要传递字符串参数
- 不要使用
std::exception
第一种情况很简单;只需使用
throw std::exception();
缺点是您不会收到描述性错误消息。
如果错误消息很重要,直接使用 std::exception
不是一个选项。在这种情况下,您可以使用 std::logic_error
或 std::runtime_error
,它们继承 std::exception
并且构造函数采用字符串参数,因此
throw std::runtime_error("Unable to format Device");
可能已经解决了问题。 catch
捕获 std::exception
的子句也将捕获 std::runtime_error
。但是,有一个潜在的问题:catch
捕获 std::runtime_error
的子句不会捕获 std::exception
但会捕获这个。
这似乎是一个极端案例,完全有可能对您来说不是问题。但是,如果调用堆栈中有一个 catch
子句捕获 std::runtime_error
但不应该捕获此代码抛出的异常,则您可以派生自己的异常 class 来自 std::exception
确实需要一个字符串参数。因为 class 是新的,所以它不会被现有的 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_error
或 std::logic_error
(或派生自 class其中之一)。
std::logic_error
还是std::runtime_error
哪个更合适,不是很明确;在这种情况下,我可能会选择 std::runtime_error
,因为该错误似乎在理论上什至不可预测,但考虑到 std::domain_error
和 std::future_error
来自 std::logic_error
,它不会是在那个层次结构中完全不合适。这个我觉得见仁见智吧。