动态转换规范(规则)说明

You*_*One 5 c++ dynamic-cast casting

我们有 dynamic_cast 的一般形式:

dynamic_cast <新类型> (表达式)

我对这条规则 (5a) 的粗体部分特别困惑:

5:如果表达式是指向多态类型 Base 的指针或引用,并且 new-type 是指向类型 Derived 的指针或引用,则执行运行时检查:

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

你能举一个例子,这部分不满足吗?

以上摘录来自cppreference:cppreferenc

Nat*_*son 5

充实多继承示例@Peter 总结:

     Base1
     /   \  <-- Virtual inheritance here
  Base2  Base2
    |     | <-- Nonvirtual inheritance here and below
  Left   Right
    \     /
    Derived

Base1* p_base1 = new Derived();
Base2* p_base2 = dynamic_cast<Base2*>(p_base1); // Which Base2?
Run Code Online (Sandbox Code Playgroud)

Base2一个Derived对象中有两个不同的对象,那么应该p_base2指向哪一个呢?

代码示例:

#include <iostream>

struct Base1 { virtual ~Base1() = default; };
struct Base2 : virtual Base1 { };
struct Left : Base2 { };
struct Right : Base2 { };
struct Derived : Left, Right {
    Derived() : Base1() {}
};

int main()
{
    Base1* p_base1 = new Derived();
    Base2* p_base2 = dynamic_cast<Base2*>(p_base1);
    std::cout << std::boolalpha;
    std::cout << "p_base1 == nullptr: " << (p_base1 == nullptr) << '\n';
    std::cout << "p_base2 == nullptr: " << (p_base2 == nullptr);
    delete p_base1;
}
Run Code Online (Sandbox Code Playgroud)

在这里要小心一点:Base1实际上是继承的,因此只有一个Base1子对象,我们实际上可以初始化p_base1. 但是,DerivedLeftand非虚拟地继承Right,这意味着它有两个实例Base2。因此,向下转型失败。

输出:

p_base1 == nullptr: false
p_base2 == nullptr: true
Run Code Online (Sandbox Code Playgroud)