C++ 为什么基类catch子句可以捕获派生类异常。

C++ 为什么基类catch子句可以捕获派生类异常。,c++,exception,C++,Exception,我在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(i

我在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;
}
执行
catch(A)
时确实会输出hello,但当我显式定义复制构造函数时,如下所示:

explicit A( const A& other ) : m_value( other.m_value ) {
        std::cout << "hello\n";
}
显式A(常数A和其他):m_值(其他m_值){

STD::CUT< P>因为Ccatch(a…)>代码>第一个。这是C++的一个错误特性。理想地,它会给您一个编译错误: catch /Cuth.Bug无序,或者至少对于不可达代码。放<代码> catch(b…)>代码>。

< P> try块的处理程序是按外观顺序尝试的。这样就可以编写 不能执行,例如,方法是将派生类的处理程序放在对应类的处理程序之后 基类。

如果在启用警告的情况下编译,也会变得很清楚:

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
捕获吗?是的,我们可以!A
B
可以转换为
A

现在,当您创建
A
的复制构造函数时,会发生一些有趣的事情。您不能将
B
隐式转换为
A
,但异常逻辑处理并不是这样做的。它只是检查类型。根据:

处理程序是类型为
E
if
-[…]
-处理程序的类型为cv
T
或cv
T&
T
E

-[……]


在我们的例子中,
A
B
的一个明确的公共基类,处理程序的类型是
A
,因此处理程序匹配。句号。现在,事实证明我们不能实际使用处理程序,所以代码格式不正确。

问题是,如果我将复制构造函数定义为显式,它将无法编译。您应该通过引用捕获NC:<代码> catch(a &…)<代码>,同样地,如果没有可能的话,没有理由用值来捕获异常。如果知道,这是一个采访问题。即使引用,它仍然通过值,因为unFungRelad,我的C++知识早于代码>显式< /代码>。非常简单!谢谢!
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 ) {
         ^