c++构造函数初始化列表抛出异常

时间:2021-09-05 22:49:36

I have a problem with the following code. As we can see I have already handled the exception thrown by A's constructor in C's constructor, why should I bother to catch and handle the exception again in the main function?

下面的代码有问题。我们可以看到,我已经处理了A的构造函数在C的构造函数中抛出的异常,为什么还要在main函数中捕获并再次处理异常呢?

#include <iostream>

class WException : public std::exception
{
public:
    WException( const char* info ) : std::exception(info){}
};

class A
{
public:
    A( int a ) : a(a) 
    {
        std::cout << "A's constructor run." << std::endl;
        throw WException("A constructor throw exception.");
    }

private:
    int a;
};

class B
{
public:
    B( int b ) : b(b) 
    {
        std::cout << "B's constructor body run." << std::endl;
        throw WException("B constructor throw exception");
    }

private:
    int b;
};

class C : public A, public B
{
public:
    C( int a, int b ) try : A(a), B(b)
    {
        std::cout << "C's constructor run." << std::endl;
    }
    catch( const WException& e )
    {
        std::cerr << "In C's constructor" << e.what() << std::endl;
    }
};

int main( int argc, char* argv[] )
{
    try
    {
        C c( 10, 100 );
    }
    catch( const WException& e )
    {
        std::cerr << "In the main: " << e.what() << std::endl;
    }   

    return 0;
}

1 个解决方案

#1


16  

You cannot actually catch an exception in a constructor. You can handle it, but you have to rethrow it or another exception. The reason is about object integrity and object lifetimes:

在构造函数中不能捕获异常。您可以处理它,但您必须重新抛出它或另一个异常。原因是关于对象完整性和对象寿命:

If the construction of a throws, a part of c has not been initialized and is completely missing - lifetime of a never starts. a is not an optional part of C, otherwise it had to be a pointer or a std::optional (since C++14 - boost::optional before that).

如果构造了一个抛出,c的一部分没有初始化,并且完全丢失了——一个从未开始的生命周期。a不是C的可选部分,否则它必须是指针或std::optional(因为c++ 14 - boost::optional在那之前)。

So how do you assemble a C if one of its vital parts cannot be constructed? You can't. c can never start to exist as a complete object, so there is no way you can exit the constructor normally. That's the reason why if construction of a member object fails, construction of the whole object has to fail, i.e. has to throw an exception.

那么,如果C的一个重要部分不能被构造出来,你该如何组装呢?你不能。c不能作为一个完整的对象开始存在,所以您无法正常地退出构造函数。这就是为什么如果一个成员对象的构造失败了,那么整个对象的构造就必须失败,也就是说必须抛出一个异常。

If you don't throw an exception in C::C's catch block, the compiler will do so for you.

如果在C:::C的catch块中没有抛出异常,编译器将为您抛出异常。

C++ Standard, §15.3,15:

c++标准,§15.3,15:

The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor.

如果控件到达构造函数或析构函数的function-try块的处理程序的末尾,则会重新抛出当前处理的异常。

For a broader treatment on that topic, see http://www.gotw.ca/gotw/066.htm

有关这个主题的更广泛的讨论,请参见http://www.gotw.ca/gotw/066.htm

#1


16  

You cannot actually catch an exception in a constructor. You can handle it, but you have to rethrow it or another exception. The reason is about object integrity and object lifetimes:

在构造函数中不能捕获异常。您可以处理它,但您必须重新抛出它或另一个异常。原因是关于对象完整性和对象寿命:

If the construction of a throws, a part of c has not been initialized and is completely missing - lifetime of a never starts. a is not an optional part of C, otherwise it had to be a pointer or a std::optional (since C++14 - boost::optional before that).

如果构造了一个抛出,c的一部分没有初始化,并且完全丢失了——一个从未开始的生命周期。a不是C的可选部分,否则它必须是指针或std::optional(因为c++ 14 - boost::optional在那之前)。

So how do you assemble a C if one of its vital parts cannot be constructed? You can't. c can never start to exist as a complete object, so there is no way you can exit the constructor normally. That's the reason why if construction of a member object fails, construction of the whole object has to fail, i.e. has to throw an exception.

那么,如果C的一个重要部分不能被构造出来,你该如何组装呢?你不能。c不能作为一个完整的对象开始存在,所以您无法正常地退出构造函数。这就是为什么如果一个成员对象的构造失败了,那么整个对象的构造就必须失败,也就是说必须抛出一个异常。

If you don't throw an exception in C::C's catch block, the compiler will do so for you.

如果在C:::C的catch块中没有抛出异常,编译器将为您抛出异常。

C++ Standard, §15.3,15:

c++标准,§15.3,15:

The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor.

如果控件到达构造函数或析构函数的function-try块的处理程序的末尾,则会重新抛出当前处理的异常。

For a broader treatment on that topic, see http://www.gotw.ca/gotw/066.htm

有关这个主题的更广泛的讨论,请参见http://www.gotw.ca/gotw/066.htm