通过引用捕获std::异常

  • 本文关键字:std 异常 引用 c++
  • 更新时间 :
  • 英文 :


我有一个愚蠢的问题。我读过这篇关于std::exception的文章http://www.cplusplus.com/doc/tutorial/exceptions/

catch (exception& e)上,它说:

我们放置了一个通过引用捕获异常对象的处理程序(注意类型后面的&符号&(,因此这个处理程序也捕获了从异常派生的类,比如myexception类的myex对象。

这是否意味着使用"&"还可以捕获父类的异常?我想&是在std::exception中预定义的,因为传递e(std::exception(作为引用比传递对象要好。

异常使用&的原因与其说是多态性,不如说是避免切片。如果不使用&,C++将尝试将抛出的异常复制到新创建的std::exception中,这可能会在过程中丢失信息。示例:

#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
  virtual const char *what() const throw() {
    return "Hello, world!";
  }
};
int main() {
  try {
    throw my_exception();
  } catch (std::exception e) {
    std::cout << e.what() << std::endl;
  }
  return 0;
}

这将打印std::exception(在我的情况下是St9exception(的默认消息,而不是Hello, world!,因为原始异常对象因切片而丢失。如果我们将其更改为&:

#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
  virtual const char *what() const throw() {
    return "Hello, world!";
  }
};
int main() {
  try {
    throw my_exception();
  } catch (std::exception &e) {
    std::cout << e.what() << std::endl;
  }
  return 0;
}

现在我们看到了Hello, world!

这是否意味着使用"&"还可以捕获父类的异常?

不,这不会增加捕获异常的范围(例如,从包含try/catch代码的类的父类(。

与按值捕获相比,它也不会增加可以捕获的异常类型(没有&catch(std::exception e)-您仍然可以捕获std::exception或从其派生的每个异常(。

它增加的是当您捕获异常时实际获得的数据量。

如果抛出了一个从std::exception派生的异常,并且您通过值捕获它,那么您将抛出该异常类中的任何额外行为。由于Slicing,它打破了异常类上的多态性。

一个例子:

class MyException : public std::exception
{
public:
    virtual const char* what() const
    {
        return "hello, from my exception!";
    }
};
// ...
try
{
    throw MyException();
}
catch(std::exception& e)
{
    // This will print "hello, from my exception!"
    std::cout << e.what() << "n";
}
// ...
try
{
    throw MyException();
}
catch(std::exception e)
{
    // This will print "Unknown exception"
    std::cout << e.what() << "n";
}
不,&与异常处理程序的多态性完全无关。他们的措辞非常糟糕,似乎确实表明&在某种程度上负有责任。事实并非如此。你是对的,&只是通过参考,这样效率会高一点。

同样作为一条一般规则,你应该真正尝试避免cplusplus.com.

更新链接:cplusplus.com 有什么问题

在这里使用对异常的引用可以减少创建的临时对象,也可以保持多态性。

最新更新