前段时间,我在stackoverflow上发现了一个聪明的技巧,它显示了一种从runtime_error
创建派生异常类的方法,它接受wstring作为构造函数。诀窍是使用虚方法调用初始化runtime_error
库。这是看起来像:
UnknownEx(const std::wstring& s) throw() : m_msg(s), std::runtime_error( what() ) {};
what()
进行转换(我可以将wstring转换为字符串的有损转换):
virtual const char* what() const throw() {
// Convert the wstring data member to a char*.
const wchar_t* wstr = m_msg.c_str();
char *str = new char[wcslen(wstr)];
size_t *charsChanged = 0;
wcstombs_s(charsChanged, str, sizeof(str), wstr, _TRUNCATE);
return str;
}
编译很好,但是当我尝试使用它时:
throw UnknownEx(L"Test Exception");
在尝试查找数据成员what()
的长度时,应用程序在m_msg
中失败。调试what()
时,尚未设置m_msg
。似乎初始化列表技巧中的这个函数调用不起作用。
有没有办法让这个“技巧”正常工作,还是我的整个方法被误导了?
我的长期目标:我只想创建一个派生异常类,该异常类可以通过catch(exception& ex)
进行一般性捕获,但在其构造函数中接受wstring
答案 0 :(得分:3)
程序崩溃是因为在std::runtime_error(what())
之前执行了m_msg(s)
。基类在成员变量之前初始化。
虽然在这种情况下调用what()
会调用UnknownEx
覆盖,但最好不要从构造函数调用虚函数,因为语义很混乱。
如果您要将异常消息存储在自己的m_msg
成员变量中,请不要派生自std::runtime_error
;没有理由将字符串存储两次。考虑直接从std::exception
。