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/

相关文章:

javascript - 如何正确处理jquery ajax成功和失败

c++ - 使用带链表的复制构造函数

c++ - 将亮度更改为区域外的像素

c++ - FindClass 返回 null

c++ - ID3D11ShaderResourceView 的尺寸

java - Java-为什么只有一些错误抛出方法需要错误处理?

asp.net-mvc-3 - MVC 3 远程验证,编辑 View 中重复检查的问题

java - 如何以编程方式使用 Spring Validator 验证 Map<String, String>

java - 使用 java 扫描器类时如何验证用户文本输入?

java.lang.NullPointerException : println needs a message android database error