C ++构造函数初始化列表抛出异常 [英] C++ constructor initializer list throw exceptions
问题描述
我有以下代码的问题。我们可以看到我已经处理了A的构造函数在C的构造函数中抛出的异常,为什么我应该在主函数中再次捕获和处理异常?
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?
#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;
}
推荐答案
捕获构造函数中的异常。你可以处理它,但你必须重新抛出它或另一个异常。原因是关于对象完整性和对象生命周期:
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:
如果构造 a
throws, c $ c> c 尚未初始化并完全丢失 - a
的生命周期永远不会开始。 a 不是
C
的可选部分,否则必须是指针或 std :: optional
(因为C ++ 14 - boost :: optional
之前)。
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
的重要部分,那么如何组装它呢?你不能。 c
永远不会开始作为一个完整的对象存在,所以没有办法你可以正常退出构造函数。这就是为什么如果构造一个成员对象失败,整个对象的构造必须失败,即必须抛出异常。
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
的catch块中抛出异常,编译器会为你这样做。
If you don't throw an exception in C::C
's catch block, the compiler will do so for you.
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.
有关该主题的更广泛的处理,请参阅 http://www.gotw.ca/gotw/066.htm
For a broader treatment on that topic, see http://www.gotw.ca/gotw/066.htm
这篇关于C ++构造函数初始化列表抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!