首页 > 解决方案 > 如何正确使用 dynamic_cast 向下转换?

问题描述

我很困惑dynamic_castC++ Primercppreference (规则 5)中的材料无法帮助我理解。(cppreference 比这本书要难得多,我都非常仔细地阅读了它们)

C++ Primer 5th开始:
dynamic_cast<type*>(e)

在所有情况下,类型e必须是从目标类型公开派生的类类型、目标类型的public基类或与目标类型相同。如果e具有这些类型之一,则演员表将成功...

所以这就是我如何理解上面引用的文字:

(基类有虚函数)

dynamic_cast成功,如果:

  1. e是从type. e是孩子。上调。
  2. e是一个基类typetype是孩子。沮丧。
  3. e与 相同type。边播?

示例代码:

#include <iostream>
using namespace std;

struct A {
    virtual void foo() {}
};

struct B : A {

};

struct C : B {

};

int main()
{
    A* pa = new B;
    if (C* pc = dynamic_cast<C*>(pa)) {
        cout << "1";    //B is a base class of C
    }
    return 0;
}

我不明白为什么这种沮丧会失败,我认为它满足条件 2.规则 5)(来自 cppreference)。


如果这本书是错误的(又一次该死),有人会从 cppreference详细说明规则 5)吗?没有例子,我无法完全理解它所说的......

标签: c++dynamic-castdowncast

解决方案


这是来自 cppreference 的规则和我的注释:

5) 如果 expression 是指向多态类型 Base 的指针或引用,并且 new_type 是指向 Derived 类型的指针或引用,则执行运行时检查:

这适用。B是 的基础C

a) 检查由表达式指向/标识的最派生对象。如果在该对象中,表达式指向/引用 Derived 的公共基,并且如果只有一个 Derived 类型的子对象是从表达式指向/标识的子对象派生的,则转换的结果指向/引用该 Derived 子对象。(这被称为“沮丧”。)

指向的最衍生对象pa是类型B

虽然B是 的公共基础,但指向C的特定实例不是实例的基础子对象的实例。指向的实例是一个“具体”对象。所以,本案不适用。paBCB

一个例子:

C  c;
B* bp = &c; // bp points to base subobject of C
C* cp = dynamic_cast<C*>(bp);
assert(cp);

B  b2;
B* bp2 = &b2; // bp does not point to a base subobject
C* cp2 = dynamic_cast<C*>(bp2);
assert(!cp2);

b) 否则,如果表达式指向/引用最派生对象的公共基类,并且同时,最派生对象具有 Derived 类型的明确公共基类,则转换的结果指向/引用派生对象(此被称为“边播”。)

pa不指向基类为 的最派生对象C,因此这种情况不适用。

侧投的一个例子:

struct base {
    virtual ~base(){}; // for polymorphism
};
struct left : base {};
struct right : base {};
struct derived : left, right {};

derived d;
left* l = &d;
right* r = dynamic_cast<right*>(l);

c)否则,运行时检查失败。如果在指针上使用了 dynamic_cast,则返回 new_type 类型的空指针值。如果它用于引用,则抛出异常 std::bad_cast。

5a 和 5b 的情况都不适用,所以这种“否则”的情况 5c 是适用的。


  1. e 与类型相同。边播?

不是旁观者。边播在 5b 中解释。转换为相同类型只是一个身份转换(很少有用,因此也不是常用的术语)。


本书尝试的条件可能描述了转换是否格式良好。虽然,“那么演员就会成功”当然似乎意味着更多。引用的规则对于描述强制转换是否在运行时成功是不正确的。

如果整个程序格式正确,则编译器必须编译该程序。如果表达式格式错误,则编译器必须给您一条诊断消息,说明您做错了。

您展示的示例程序格式正确,并且必须成功编译。它确实在我的系统上编译。


推荐阅读