c++ - 在构造函数中进行错误处理而不会失败

标签 c++ validation error-handling

我目前正在建立一个库,该库分析用于硬件配置的XML定义(从制造商处获得)。
我已经将XML类型映射到c++类,并且我使用了std::optional,只要在语义上对丢失的那部分数据正确,就可以使用可选的XML成员。

我现在正试图为我的数据类型提出一个好的错误处理策略。
有时,XML可能会丢失一些被模式标记为required的信息,或者可能找不到所需的元素(这与丢失所需数据的元素是不同的错误)。

所有类型的基本概念都遵循此(示例)类:

class TMyXmlType {
  std::string name;
  std::optional<int> factor;
  std::optional<int> minFactor;
  std::optional<int> maxFator;
public:
  TMyXmlType(const xml_node & root){
    if(root){ // Check if the element exists
    name = root.value();
      if(root.has_child("factor"){ factor = root.child("factor").value(); }
      if(root.has_child("minFactor"){ factor = root.child("minFactor").value(); }
      if(root.has_child("maxFator"){ factor = root.child("maxFator").value(); }
    }else{
      // What do I do here?
    }
  } 
  operator Json::Value() const {
    if(/*object constructed correctly?*/){
      Json::Value asJson;
      asJson["name"] = name;
      if(factor.has_value()){ asJson["factor"] = factor.value(); }
      if(minFactor.has_value()){ asJson["minFactor"] = minFactor.value(); }
      if(maxFator.has_value()){ asJson["maxFator"] = factor.maxFator(); }
      return asJson;
    }else{
      // return error object?
    }
  }
}


到现在为止还挺好。可选成员正在得到照顾。
但是,root可能是一个空节点(如果未找到,xml解析库将返回一个空节点。)。
如果没有找到一个或多个必需的XML节点,我基本上想返回一个错误对象而不是类的值(在我的运算符(operator)函数中)。

据我所能发现的,对于现代C++,如果构造函数无法正确构造对象,则应该引发异常,但是,如果引发异常,则我的聚合数据类型将包含大量的构造函数,并且对每个必需的数据成员尝试/捕获块,这将使代码库难以阅读和维护。

所以现在的问题是:如果缺少必需的成员,让运算符(operator)返回错误对象而不是类数据的最干净方法是什么?

我不需要构造函数显式失败,就目前而言,它也永远不会抛出(据我所知),我真的希望将错误对象提供给调用者,而不是返回代码或冒泡异常。

最佳答案

简单明了,当您不希望犯错时,不要做任何花哨的事-例如。做就是了:

class TMyXmlType {
  std::string name;
  std::optional<int> factor;
  std::optional<int> minFactor;
  std::optional<int> maxFator;
public:
  TMyXmlType(const xml_node & root){
    if(root){ // Check if the element exists
    name = root.value();
      if(root.has_child("factor"){ factor = root.child("factor").value(); }
      if(root.has_child("minFactor"){ factor = root.child("minFactor").value(); }
      if(root.has_child("maxFator"){ factor = root.child("maxFator").value(); }
    }else{
      name = "NODE_ERROR";
    }
  } 
}

话虽这么说-重新考虑您的设计-将无效的节点传递给构造函数可能是一个错误,您不希望沉默并且应该引发异常!

(但要在更高层次上捕获异常(exception)-并非针对每一个构造-可能是您潜在的误解)

检查是否找到要搜索的节点应该在调用搜索的级别进行。例如。以下代码对我来说似乎很明智:
const auto& node_found = searchNode(...);

const auto optXmlType = node_found ? std::make_optional<TMyXmlType>(node_found) : std::nullopt;

但是,您可能需要将其包装在函数中。

关于c++ - 在构造函数中进行错误处理而不会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58300197/

相关文章:

c++ - 如何定期唤醒 C++ 11 线程?

c++ - 空数独填充 C++

validation - GWT CellTable 验证

java - 根据 WSDL 验证 SOAP 消息

swift - fatal error : unexpectedly found nil while unwrapping an Optional value - Duc Tran

ruby-on-rails - 事件记录错误消息form_tag Rails 3

c++ - 检查 map 中是否存在键然后更新值

c++ - 如何使用 C++ 在 SFML 中正确生成随机地形

forms - 输入类型编号 "only numeric value"验证

email - 发生错误/异常时如何从jBoss发送电子邮件?