我有一个愚蠢的问题。我读过这篇关于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 有什么问题
在这里使用对异常的引用可以减少创建的临时对象,也可以保持多态性。