3

这里是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;
}

这里是f1()

void f1(A& subject)
{
    throw subject;
}    

信息:

B 继承自 A。A::print()是虚拟的,并在 B 中重新实现。捕获异常的 catch 是catch(A& a_ref),我认为这是有道理的,因为异常的静态类型(主题)是 A&。但是,为什么不B:: print()运行?动态类型“丢失”了吗?只A::print()在行中运行a_ref.print();

有人可以解释一下吗?

4

5 回答 5

6

throw只抛出它后面的表达式类型的对象。在这种情况下,subjectis 的类型A&,不管实际对象是什么,A都会抛出 an (注意不能抛出引用,所以会创建一个副本)。

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

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

于 2009-08-03T10:55:39.263 回答
6

根据 C++ 标准 15.1/3:

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

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

于 2009-08-03T11:03:27.370 回答
5

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

于 2009-08-03T10:55:31.743 回答
4

Catch 块以多态方式工作,但 throw 不能。当你说:

void f1(A& subject)
{
    throw subject;
}

尽管传递给函数的东西是 B,但您正在抛出 A。

于 2009-08-03T11:00:15.600 回答
-1

因为您通过引用捕获对象是“切片”的。

如果您真的想要多态行为,请尝试使用类似 pimpl idiom 的东西。

于 2009-08-03T10:56:10.167 回答