使用 static_cast 的有用向下转换示例,它不会产生未定义的行为

Example of useful downcast with static_cast which does not produce undefined behaviour

我想知道在 没有未定义行为 的情况下,通过 static_cast 应用向下转换的简短代码示例。 我环顾四周,发现有很多文本(帖子、问答等)提到了标准的片段、解释等。 但我没有找到任何例子来说明这一点(这让我感到惊讶)。

谁能提供一个这样的例子?

一个非常基本的例子:

class Animal {};
class Dog : public Animal {};

void doSomething() {
  Animal *a = new Dog();
  Dog *d = static_cast<Dog*>(a);
}

一个更人为的例子:

class A { public: int a; };
class B : public A {};
class C : public A {};
class D : public B, public C {};

void doSomething() {
  D *d = new D();
  int bValue = static_cast<B*>(d)->a;
  int cValue = static_cast<C*>(d)->a;

  // This does not work because we have two a members in D!
  // int eitherValue = d->a;
}

还有无数其他情况,由于程序中的某些标志或不变量,您知道实例的实际类型类型。但是,许多消息来源建议在所有情况下都首选 dynamic_cast 以避免错误。

通过 static_cast 进行的向下转换是 Curiously recurring template pattern (CRTP) 典型实现的一部分。来自 wikipedia 的示例:

template <class T> 
struct Base
{
    void interface()
    {
        // ...
        static_cast<T*>(this)->implementation();
        // ...
    }

    static void static_func()
    {
        // ...
        T::static_sub_func();
        // ...
    }
};

struct Derived : Base<Derived>
{
    void implementation();
    static void static_sub_func();
};

Base“知道”它可以通过 static_cast(而不是 dynamic_cast)将 this 向下转换为 T*,因为 Base 将被 T 继承。有关 CRTP 的更多详细信息,请参阅维基百科文章。