以多态方式捕获异常

3 c++ virtual inheritance reference exception

这是main():

int main()
{
    B b(1,"two","three");
    try
    {
        f1(b);
    }
    catch(B& b_ref)
    {
        cout<<"Caught B&"<<endl;
        b_ref.print();
    }
    catch(A& a_ref)
    {
        cout<<"Caught A&"<<endl;
        a_ref.print();
    }

    system("pause");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是f1():

void f1(A& subject)
{
    throw subject;
}    
Run Code Online (Sandbox Code Playgroud)

信息:

B继承自A A::print()是虚拟的,并且在B中重新实现.捕获异常的捕获是catch(A& a_ref)我认为有意义的,因为异常'静态类型(主题)是A&.但是,为什么不B:: print()跑?动态类型"丢失"了吗?只在线上A::print()运行a_ref.print();.

有人可以解释一下吗?

Ste*_*sop 6

throw只抛出一个跟在它后面的表达式类型的对象.在这种情况下,无论实际对象是什么subject类型A&,都是类型,因此A抛出(注意不能抛出引用,因此复制).

您可以通过向引发异常的异常类添加成员函数来处理此问题.只要在每个类中实现此方法,被调用的覆盖将知道对象的运行时类型并且可以throw *this.

http://www.ddj.com/cpp/184401940


Kir*_*sky 6

根据C++标准15.1/3:

throw-expression初始化一个临时对象,称为异常对象,其类型是通过从throw的操作数的静态类型中删除任何顶级cv限定符来确定的...

因此,您创建A类型的临时对象,而不是B.


CB *_*ley 5

当您说" throw subject"时,会根据throw表达式(subject)的静态类型创建一个新的异常对象.subject作为参考的事实与确定要抛出的对象的目的无关.一个新A对象是从中构造的副本subject.此副本(或可能是此副本的副本)是捕获的实际对象.