我想抛出一个异常,其中包含有关输入/结果导致问题的详细信息。然后,当我捕获这些异常时,我可以将有用的错误消息记录到日志中我正在研究VS2012,它没有实现参数包。所以目前我使用vsprintf将变量长度参数合并到字符串中。
在错误处理阶段使用此类printf-like
函数是一种好习惯吗?
或者只是不需要在例外情况下携带这些详细信息?
例外
class VargException : std::exception
{public:
VargException (const char* fmt, ...)
{
va_list vargs;
va_start(vargs, fmt);
char buf[260] = {};
vsprintf_s(buf, fmt, args);
va_end(vargs);
msgBuilt_ = tryAssign(msg_, buf);
}
const char* what() const {
return msgBuilt_? msg_.c_str(): "Error message failed to build";
}
std::string msg_;
bool msgBuilt_;
// Updated: Avoid dynamic std::string throw exception
bool tryAssign(std::string& msg, const char* buf) throw()
{
try{ msg = buf; return true;}
catch (...) { return false; }
}
};
客户端代码
void func(int key, int len) {
try {
if(notExists(key)) { throw VargException("%d key does not exist", key); }
if(outOfRange(len)) { throw VargException("length %d is out of range.", len); }
HRESULT hr = processSomething();
if(FAILED(hr)) { throw VargException("FAILED to processingSomething. hr: 0x%08X", hr); }
} catch (VargException& e) {
std::cerr << e.what() << "\n";
}
}
答案 0 :(得分:2)
在异常创建/处理代码中,您应该对异常更加偏执。
构建std::string
可以throw.
我会添加偏执狂,否则接受设计。查找一些令牌以检测2013模式并发出警告/弃用消息。
答案 1 :(得分:1)
这似乎是一种合理的方法(除了你错过了vsprintf_s
的参数)。
请务必将其换成使用可变参数模板和I / O流的类型安全解决方案 什么时候可以。
答案 2 :(得分:1)
我发现使用std :: ostringstream而不是格式字符串会更容易。
例如:
class MessageBuilder
{
public:
MessageBuilder() {};
MessageBuilder(const char * context)
{
m_os << context << ": ";
}
// stream operator to build message
template <class T>
MessageBuilder & operator<<(const T & t)
{
m_os << t;
return *this;
}
operator std::string() const
{
return m_os.str();
}
private:
std::ostringstream m_os;
};
可以像这样使用它来构建消息。
MessageBuilder() << "This is a message containing an int: " << 3;