7

我可以理解为什么 dynamic_cast 在这种情况下确实有效:

#include <iostream>

struct A{
    virtual ~A() = default;
};

struct B {
    virtual ~B() = default;
};

struct C : A, B{};

void f(const A &a) {
    if(auto p = dynamic_cast<const B*>(&a))
        std::cout << "a is a B" << std::endl;
}

int main() {
    f(C{});

    return 0;
}

但是为什么如果你从 B 中删除多态性它仍然有效:

#include <iostream>

struct A{
    virtual ~A() = default;
};

struct B {
};

struct C : A, B{};

void f(const A &a) {
    if(auto p = dynamic_cast<const B*>(&a))
        std::cout << "a is a B" << std::endl;
}

int main() {
    f(C{});

    return 0;
}

是不是因为 dynamic_cast 必须只知道你给的对象的真实类型有一个参数(就像dynamic_cast<void*>/ typeid 会做的那样),而在它知道真实类型之后,它才知道该类型是否是从非多态基派生的?

4

1 回答 1

8

根据标准([expr.dynamic.cast]p6),您转换的对象应该具有多态类型,而不是您尝试转换的对象。

如果你仔细想想,这绝对是合乎逻辑的。dynamic_cast需要一些信息来进行强制转换 (RTTI),并且此信息与多态类型相关联。所以不管这个类型的父类是否是多态的,关于这个类的信息就在这里。您无需知道其他类的 RTTI 即可将此对象转换为它。你只需要知道这个对象是否真的与你想要转换的对象有某种关系。

于 2018-09-04T17:04:17.470 回答