通过引用捕获std :: exception?

use*_*069 18 c++

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

catch (exception& e),它说:

我们已经放置了一个通过引用捕获异常对象的处理程序(注意&符号和类型之后),因此这也捕获了从异常派生的类,就像myexception类的myex对象一样.

这是否意味着通过使用"&"您还可以捕获父类的异常?我认为&是在std :: exception中预定义的,因为最好将e(std :: exception)作为引用传递给对象.

bdo*_*lan 56

使用&异常的原因并不是避免切片这样的多态性.如果您不使用&,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;
}
Run Code Online (Sandbox Code Playgroud)

这将打印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;
}
Run Code Online (Sandbox Code Playgroud)

现在我们确实看到了Hello, world!.

  • +1; 哇,你的例子和答案看起来非常像我的.你坐在我身后吗?;) (3认同)

Mer*_*ham 8

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

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

与按值捕获相比,它也不会增加可捕获的异常类型(catch(std::exception e)没有&- 你仍将捕获每个异常std::exception或者从中获取的异常).

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

如果抛出的异常是派生的std::exception,并且您按值捕获它,那么您将抛弃该异常类中的任何额外行为.由于切片,它打破了异常类的多态性.

一个例子:

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";
}
Run Code Online (Sandbox Code Playgroud)