我已尝试在Xcode上使用代码
#include <iostream>
/*Exceptions*/
struct A {
A( int value ) : m_value( value ) {}
int m_value;
};
struct B : A {
B( int value ) : A( value ) {}
};
//+++++++++++++++++++++++++++++++
/*Exceptions End*/
int main(int argc, const char * argv[]) {
try {
try {
throw B( 5 );
}
catch ( A a ) {
a.m_value *= 2;
}
catch ( B b ) {
b.m_value -= 2;
throw b;
}
}
catch ( A a ) {
std::cout << a.m_value;
}
return 0;
}
这里抛出的异常类型是B,但是catch( A a )
抓住了B.
我对此有所考虑,但不知道它是否正确。我认为这是因为A的复制构造函数接受const A&
可以匹配B类型对象,复制构造函数隐式地将数据类型从B转换为A.为了确认这一点,我为{{1}添加了复制构造函数}}:
struct A
执行A( const A& other ) : m_value( other.m_value ) {
std::cout << "hello\n";
}
时会输出hello,但是当我明确定义复制构造函数时,如下所示:
catch( A a )
编译器叫喊&#34;没有匹配的构造函数用于初始化&#39; A&#39;&#34;。
我不知道为什么。为什么它没有跳转到explicit A( const A& other ) : m_value( other.m_value ) {
std::cout << "hello\n";
}
?
答案 0 :(得分:2)
尝试块的处理程序按外观顺序进行尝试。这使得编写处理程序成为可能 永远不能执行,例如通过在对应的处理程序之后放置派生类的处理程序 基类。
如果编译时启用了警告,那么这也会变得清晰:
main.cpp:28:9: warning: exception of type 'B' will be caught
catch ( B b ) {
^
main.cpp:24:9: warning: by earlier handler for 'A'
catch ( A a ) {
^
所以是的,最终发生的事情是抛出一次B
,我们只是逐个查看处理程序列表。我们能赶上A
吗?我们可以! B
可转换为A
。
现在,当你制作A
的复制构造函数时,会发生一些有趣的事情。您无法将B
隐式转换为A
,但这不是异常逻辑处理的作用。它只是检查类型。根据{{3}}:
处理程序是类型
E
的异常对象的匹配,如果是 - [...]
- 处理程序的类型为 cvT
或 cvT&
,而T
是E
的明确公共基类}或者
- [...]
在我们的例子中,A
是B
的明确公共基类,处理程序的类型为A
,因此处理程序匹配。完全停止。现在,事实证明我们实际上使用处理程序,因此代码格式不正确。
答案 1 :(得分:0)
因为catch (A ...)
是第一位的。这是C ++的错误。理想情况下,它会给你一个无序的catch
块的编译错误,或至少是无法访问的代码。先放catch (B ...)
。