我知道downcasting基本上是将父类指针或引用转换为派生类引用或指针的转换,为此您需要使用dynamic_cast运算符。但我几乎想不出任何例子。你们能否解释一下?
我知道downcasting基本上是将父类指针或引用转换为派生类引用或指针的转换,为此您需要使用dynamic_cast运算符。但我几乎想不出任何例子。你们能否解释一下?
向下转型在什么情况下实际上是有用的?
当实现神奇的递归模板模式(Curiously recurring template pattern,CRTP)时,向下转型非常有用:
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();
};
常见的基类模板接口提供了定义,将调用委托给派生类实现,对于非静态成员函数,通过将基类的this
指针向下转换为相应派生类的指针类型(针对基类模板的特定专业化),然后分派到派生类函数来实现。请注意,在这种情况下,向下转换不一定需要使用动态转换来实现;在此示例中,使用静态转换将基类指针(this
)转换为相应的派生类指针。如果你从不太信任的外部/用户代码中获取抽象类,需要验证它是否与你期望的类型匹配。如果不匹配,应报告错误而不是进入未定义行为。此外,如果你将过多的代码/类暴露给用户/外部代码,这将是一个问题 - 因此你需要将它们隐藏在接口类后面。
对于通用对象管理器类非常有用 - 它存储了不理解其内容的抽象类。因此,每当用户尝试获取其中之一并转换为适当的类型时,应该进行动态转换以确保用户没有搞乱类型。
它需要处理具有非平凡层次结构的复杂类 - 对于这些类,简单的指针转换可能会失败。虽然一般情况下不建议处理这样的类。
在虚幻引擎中广泛使用向下转型。甚至有一个专门的Cast
函数,用于操作UObject
派生类型的整数表示,这使得它在性能方面非常便宜。
该引擎带有一组基础类型层次结构,应该在您的游戏模块中进行继承和扩展。问题是这些类型持有指向自身的基类型指针,因此当您扩展这些类型时,仍将使用基础引擎类型定义的变量,除非您定义自己的变量-尽管这不会给您完全的支持。
在虚幻引擎游戏代码库中,像下面的代码是常见的情况。
ACharacter* Character = GetCharacter(); // Base engine character type.
AMyCharacter* MyCharacter = Cast<AMyCharacter>(Character); // Extended game character type.
MyCharacter->Something();
template<typename T>
T* TagMixin::ObjectFromTag(Tag tag)
{
TagMixin * p = TableLookup(tag);
if (p == nullptr) // (not found)
return nullptr;
return dynamic_cast<T*>(p);
}
dynamic_cast
表明设计存在缺陷(即使我自己的代码中使用了它,真是太糟糕了)。可能有一些合法的使用情况,但我还没有遇到过。 - Eljaystatic_cast
也可以执行向下转换。 - HolyBlackCat