3

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

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 - 但它需要在调用之前预先实例化错误字符串,并将批量添加到 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)
  • 调用者不必在函数调用之前创建任何专门的变量,并且仍然可以将函数结果视为布尔值 - 或者在错误未被忽略的情况下,轻松检索解释
  • 下一个程序员可以通过查看函数定义来了解正在使用的错误模型

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

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

4

1 回答 1

3

将“错误”分为两类会很有用:

致命错误

这些是恢复毫无意义的错误。

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);
  }
}
于 2012-07-06T16:35:27.897 回答