如果发生异常,则在不使用异常时返回非流动函数的返回?C

What to return for a non-void function when exception occurs, without using exception? C++

本文关键字:异常 返回 函数 如果      更新时间:2023-10-16

我正在尝试实现二进制搜索树。我有私人和public get()方法。对于private get(),我返回节点对象,或者如果找不到该节点,则返回例外。对于public get(),我返回节点对象的值,即std :: string或捕获该异常。用户仅调用public get(),我正在尝试避免让用户使用异常。这就是为什么我在public get()中捕获异常而不是向用户重新研究它的原因。我的问题是,当public get()捕获异常时,如何终止函数,因为我的返回类型是std :: string。我试图返回-1或std :: terminate(),但它们没有起作用。有什么方法可以处理此问题,或者我必须重新换一个例外或更改我的返回类型?谢谢。这是我的代码。

// public
std::string BST::get(int key) {
  Node *node;
  try {
    node = get(key, my_root);
  } 
  catch (const std::out_of_range& oor) {
    std::cout << oor.what() << std::endl;
    // How to let the function terminate here?
  }    
  return node->value;
}
//private
Node* BST::get(int key, Node* root) {
  if (root == NULL) {
      throw std::out_of_range("Cannot find.");
  }
  if (key < root->key) {
      return get_node(key, root->left);
  } else if (key > root->key) {
      return get_node(key, root->right);
  } else {
      return root;
  }
}

考虑与布尔和字符串返回一对。

std::pair<bool, std::string> BST::get(int key) {
    Node *node;
    try {
        node = get(key, my_root);
    } 
    catch (const std::out_of_range& oor) {
        std::cout << oor.what() << std::endl;
        // How to let the function terminate here?
        return std::make_pair(false, "");
    }    
    return std::make_pair(true, node->value);
}

使用魔术值表明缺少该值的问题是,总有可能实际使用值。

您需要保留一个可能的退货值以表示错误。

例如,返回的std::string可能包含一个空字符串("") - 假设如果没有发生错误,则无法返回空字符串。

如果返回指针,则返回NULL非常常见地指示错误。

如果返回int,请选择一些指示错误的值(如果仅预期结果,常见选择为零,则INT的最大值)。

通常,返回特定值是API协议。通常,它会像一个空白字符串一样,但是如果空白字符串是有效的返回,则可能是其他可能不会出现的值。

std::string BST::get(int key) {
    Node *node;
    try {
        node = get(key, my_root);
    } 
    catch (const std::out_of_range& oor) {
        return std::string("0xDEADBEEF");
    }    
    return node->value;
}

否则,您可以使用C样式的返回,在此返回一个整数,指定它是否有效,并在发现的情况下采用其他参数以填充OUPUT。(我知道的不是很喜欢C ,但它有效!)

我的问题是,当public get()捕获异常时,如何终止函数

return语句在您的功能中的任何位置都有效。

它表示控件应返回到称为它的函数。

std::string BST::get(int key) {
  Node *node;
  try {
    node = get(key, my_root);
  } 
  catch (const std::out_of_range& oor) {
    std::cout << oor.what() << std::endl;
    return std::string(); // I choose the empty string to mean "key not found"
  } 
  return node->value;
}

您问题的最佳自我评估解决方案是:

  1. 返回在您的预期返回类型上模板的专用类,该类可容纳相关的错误信息。因此,该课程将被命名,例如template<class T> class Expected { /* ... /* }。要深入研究此选项,请检查Alexandresu的谈话:C 中的系统错误处理。您还可以找到将其纳入Boost的建议:Boost。Google Summer of Code提案。或进入标准:添加公用事业类以代表预期的单元的提议。由于所有这些只是建议,并且由于我发现这样的错误处理非常针对项目,因此您当然需要沿着参考文献推出自己的课程。

    1. 使用boost::optional<std::string>。事实上的标准答案是您问题的答案。它没有将错误信息放在意外情况下的空间,但这对于您的用例似乎无关。

有两种基本方法:

  1. 您保留一个特殊的价值来发出错误条件。

  2. 您使用侧通道传达错误条件。这是我想到的可能侧渠道的完整列表:

    1. 您将指针返回到字符串。这使您可以在发生错误的情况下返回nullptr(指针值是侧频道)。

    2. 您返回一个包含预期返回值和可能的错误条件的对象。

    3. 您使用一个参考/指针参数作为侧渠道。例如,您可以将您的公共Getter声明为:

      std::string get(int key, int* error = nullptr);
      

      如果error参数不是null,则只需设置*error即可发出错误是否发生。在错误的情况下,您还会返回一个空字符串(与error是否为null)。

每个都有一些优势,有些缺点。这是一些更重要的:

  • 特殊值限制了可能的用途。除非您确切地知道用户所需的内容(不太可能),否则使用空字符串将不允许您的类使用。一些用户将需要存储空字符串。

  • 返回std::pair<>或类似的返回使使用情况笨拙。返回的对象需要使用新变量明确地进行内省。

  • 同样,错误参数方法需要在调用函数之前声明错误参数的变量。但是,如果用户满足您在错误上返回的值,则它也可以传递nullptr。IE。需要空字符串作为值的用户将使用错误参数,不需要区分空字符串和未设置值的用户不需要做任何特别的事情。