C++错误处理模式

C++ error handling pattern

本文关键字:模式 处理 错误 C++      更新时间:2023-10-16

我们有一个庞大的代码库,其中包含大量代码来执行此类操作:

bool DoSomething(CString Value)
{
   if(Value == "bad")
   {
       AfxMessageBox("description of error");
       return false;
   }
   return true;
}

甚至只是这个:

bool DoSomething(CString Value)
{
   if(Value == "bad")
   {
      return false;
   }
   return true;
}

我们考虑了各种替代方案:

  • 例外 - 基本上我们卖的是缺点,如下所述: http://www.codeproject.com/Articles/38449/C-Exceptions-Pros-and-Cons
  • 传递一个额外的字符串 ref parm,该参数填充了错误文本 - 但它需要在调用之前预先实例化错误字符串,并将批量添加到参数列表中
  • 填充一个"last_error"成员变量 - 这似乎遭受了(imo)这里表达的缺点:GetLastError()是一种设计模式吗?这是好的机制吗?
  • 传回一个枚举(或类似),该枚举可以通过其他函数映射到错误的描述 - 但这对于小函数和对象来说感觉很"沉重",并且还在错误发生的位置和维护消息的地方之间创建了空间(尽管我想在多语言环境中他们会欣赏文本的集中化)。

所以我想知道我们是否可以创建一组如下所示的类:

class CResult
{
protected:
   CResult()
   {
      // Don't have to initialize because the derived class will do it
   }
public:
   operator bool() { return m_Result; };
   bool m_Result;
   CString m_Message;
};
class CSuccess : public CResult
{
public:
   CSuccess()
   {
       m_Result = true;
   }
};
class CFailure : public CResult
{
public:
   CFailure(const CString & Message)
   {
      m_Result = false;
      m_Message = Message;
   }
};

那么上面的代码可能看起来像这样:

CResult DoSomething(CString Value)
{
   if(Value == "bad")
   {
      return CFailure("description of error");
   }
   return CSuccess();
}

我喜欢它的地方:

  • 代码仍然可读,错误消息在错误条件附近维护
  • 程序员会更被迫在错误条件下实际提供一个错误字符串(是的,他们可以提供空白,但这似乎是一个更令人震惊的错误,imo)
  • 调用
  • 者不必在函数调用之前创建任何专用变量,并且仍然可以将函数结果视为布尔值 - 或者在错误未被忽略的情况下,轻松检索解释
  • 下一个程序员只需查看函数定义即可使用什么错误模型

我看到的主要缺点是成功的开销更高,因为一个对象、一个字符串和一个布尔值都将被实例化 - 但很多时候在我们的应用程序中,有问题的代码对性能不敏感,例如验证用户输入等。

我是否错过了其他一些大缺点? 有没有更好的解决方案?

"错误"分为两类可能很有用:

致命错误

这些是恢复没有意义的错误类型。

void check(bool cond, const string& msg)
{
  if (!cond)
  {
    // eventually log it somewhere
    std::cerr << "Fatal: " << msg << std::endl;
    exit(1);
  }
}

异常错误

这些是您可以从中恢复并使程序保持运行状态的错误类型。

void check_ex(bool cond, const string& msg)
{
  if (!cond)
  {
    // eventually log it somewhere
    throw std::runtime_error(msg);
  }
}