在此“错误和异常处理” Boost 网页中的“我应该如何设计我的异常类? ”段落中,内容如下:
[...] 3.不要嵌入 std::string 对象或复制构造函数可能引发异常的任何其他数据成员或基类。
我必须定义一个异常类来表示文件访问时某种形式的运行时错误,所以我想从 派生它std::runtime_error
,并添加一个FileName()
属性来访问发生错误的文件名。
为简单起见,我的意图是添加一个std::wstring
数据成员来存储文件名(以 Unicode 格式),但上述建议阻止了我。那么,我应该使用一个简单的wchar_t
缓冲区作为数据成员吗?
在现代桌面系统(这是我这个项目的目标平台)上,关注文件名的动态字符串分配真的很重要吗?这种分配失败的可能性有多大?我可以理解 Boost 对嵌入式系统等资源有限系统的建议,但它也适用于现代台式电脑吗?
//
// Original design, using std::wstring.
//
class FileIOError : public std::runtime_error
{
public:
FileIOError(HRESULT errorCode, const std::wstring& filename, const char* message)
: std::runtime_error(message),
m_errorCode(errorCode),
m_filename(filename)
{
}
HRESULT ErrorCode() const
{
return m_errorCode;
}
const std::wstring& FileName() const
{
return m_filename;
}
private:
HRESULT m_errorCode;
std::wstring m_filename;
};
//
// Using raw wchar_t buffer, following Boost's guidelines.
//
class FileIOError : public std::runtime_error
{
public:
FileIOError(HRESULT errorCode, const wchar_t* filename, const char* message)
: std::runtime_error(message),
m_errorCode(errorCode)
{
// Safe string copy
// EDIT: use wcsncpy_s() with _TRUNCATE, as per Hans Passant's suggestion.
wcsncpy_s(m_filename, filename, _TRUNCATE);
}
HRESULT ErrorCode() const
{
return m_errorCode;
}
const wchar_t* FileName() const
{
return m_filename;
}
private:
HRESULT m_errorCode;
wchar_t m_filename[MAX_PATH]; // circa 260 wchar_t's
};