繁体   English   中英

C++ 中的异常处理程序 catch(...)

[英]Exception handler catch(...) in C++

我了解 C++ 中的异常处理程序 catch(...) 可以处理任何类型的异常。 我想知道如果它必须处理某些 class 类型的异常会发生什么 - 是通过引用或按值传递给此处理程序的 class 的 object 吗?

这是有助于理解这一点的代码。 When the exception of type B is thrown in "Inner try", an unnamed temporary object of class B is created with the default constructor of class B. When I run this program, copy constructor of class B doesn't get called at all,而这个未命名的临时 object 的 class B 只有在执行“Outer try 3”后才被销毁,这意味着 object 一直向后传播到“Outer try 3”。 所以我的猜测是对象是通过引用传递给 catch(...) 处理程序的,但我想看看这是否是正确的推理。

#include <iostream>

using namespace std;

class A {
public:
    A() {
        cout << "Default constructor of class A" << endl;
    }
    A(const A& a) {
        cout << "Copy constructor of class A" << endl;
    }
    A(A&& a) noexcept {
        cout << "Move constructor of class A" << endl;
    }
    ~A() {
        cout << "Destructor of class A" << endl;
    }
};

class B {
public:
    B() {
        cout << "Default constructor of class B" << endl;
    }
    B(const B& b) {
        cout << "Copy constructor of class B" << endl;
    }
    B(B&& b) noexcept {
        cout << "Move constructor of class B" << endl;
    }
    ~B() {
        cout << "Destructor of class B" << endl;
    }
};

int main() {
    try {
        try {
            try {
                try {
                    throw A();
                }
                catch (A a) {
                    cout << "Inner try" << endl;
                    throw B();
                }
            }
            catch (...) {
                cout << "Outer try 1" << endl;
                throw;
            }
        }
        catch (...) {
            cout << "Outer try 2" << endl;
            throw;
        }
    }
    catch (...) {
        cout << "Outer try 3" << endl;
    }
}

当你抛出异常时,异常 object是从throw的操作数创建的。 它是以未指定方式存储的 object。

当到达异常的匹配处理程序并且处理程序不是...时,处理程序的参数从异常 object 初始化。

本质上,如果您将catch参数声明为非引用类型,您将在处理程序中获得异常 object(或基本 class 子对象)的副本。 这就是您在A处理程序中看到的内容以及为什么会调用复制构造函数。 副本一直存在,直到处理程序退出。 如果您将参数声明为引用类型,那么您将获得对异常 object 的引用,并且如果您重新抛出异常,它将始终引用相同的 object。

用投掷重新throw; 实际上并没有对catch子句的参数做任何事情。 它只是导致异常处理继续搜索catch子句和堆栈展开。 异常 object 仍然相同。

如果处理程序是catch(...) ,这一切都不会改变。 处理程序中没有要初始化的变量(引用与否),而是throw; 将重新抛出并继续搜索具有相同异常 object 的处理程序。

当处理程序退出而不重新抛出异常时,异常 object 将被销毁。 这发生在B异常 object 的最外层catch的末尾以及A异常 object 的最内层catch的末尾。 (您会收到两个对A析构函数调用,一个用于catch参数,一个用于异常 object。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM