当需要dynamic_cast并且根本无法解决时,谁能给我一个真实的案例示例?我能想到的示例通常可以通过双重调度来解决。
如果约束太强,那么 dynamic_cast 通常是要走的路的例子也很好。
我希望看到真实的例子,而不是“它通常用于在类型树上下类型之间进行转换”。
当需要dynamic_cast并且根本无法解决时,谁能给我一个真实的案例示例?我能想到的示例通常可以通过双重调度来解决。
如果约束太强,那么 dynamic_cast 通常是要走的路的例子也很好。
我希望看到真实的例子,而不是“它通常用于在类型树上下类型之间进行转换”。
双重分派要求正在交互的类型对彼此的内部有深入的了解,因为它要求一个类调用另一个类的方法。dynamic_cast
当您无法修改类的内部或不希望破坏相关类的封装时有效。
也就是说,双重调度对所涉及的类具有侵入性,而在dynamic_cast
不知道类中的演员表的情况下工作。
dynamic_cast
如果您不知道将调用的目标方法重载,也可以使用。例如,请参阅我昨天发布的这个问题。
基类 Shape 必须知道所有派生类,从而导致循环依赖。如果从 Shape 派生一个新类(比如 Triangle),则必须更新 Shape 的接口和所有其他派生类的接口/实现。在某些情况下,这甚至不是一个选项:您可能没有 Shape 的源代码,或者不愿意或不允许修改它。
“根本无法解决”的约束太强了。任何 C++ 特性都可以在 C 中进行模拟。要解决该特性,您所要做的就是在 C++ 中使用该 C 代码。例如,MFC,一个起源于 1998 年语言标准化之前的库,提供并且仍然提供它自己的动态转换。
您通常需要动态转换的一个示例是访问者模式,例如用于事件处理。访问的想法是集中动态转换,以便在整个代码中没有大量的动态转换,而是有一个:
#include <stdio.h>
void say( char const s[] ) { printf( "%s\n", s ); }
struct Event
{
struct Handler
{
virtual void onEvent( Event& ) = 0;
};
virtual void dispatchTo( Handler& aHandler )
{
aHandler.onEvent( *this );
}
template< class SpecificEvent >
static void dispatch( SpecificEvent& e, Handler& aHandler )
{
typedef typename SpecificEvent::Handler SpecificHandler;
// The single dynamic cast:
if( SpecificHandler* p = dynamic_cast<SpecificHandler*>( &aHandler ) )
{
p->onEvent( e );
}
else
{
e.Event::dispatchTo( aHandler );
}
}
};
struct FooEvent
: Event
{
struct Handler
{
virtual void onEvent( FooEvent& ) = 0;
};
virtual void dispatchTo( Event::Handler& aHandler )
{
dispatch( *this, aHandler );
}
};
struct Plane
: Event::Handler
{
virtual void onEvent( Event& ) { say( "An event!" ); }
};
struct Fighter
: Plane
, FooEvent::Handler // Comment out this line to get "An event!".
{
virtual void onEvent( FooEvent& ) { say( "Foo Fighter!" ); }
};
void doThingsTo( Plane& aPlane )
{
FooEvent().dispatchTo( aPlane );
}
int main()
{
Fighter plane;
doThingsTo( plane );
}
这个程序的输出是Foo Fighter!
。
如前所述,这是简化的。现实倾向于变得更加混乱。还有更多的代码。
干杯&hth。
我个人使用它来处理我的游戏引擎的某些部分。我有一个基实体类,我从中派生出各种其他实体。我将它们转换为基类类型,以便可以轻松地将它们存储到链表中。当我想检查列表中的特定条目是否属于某个实体时,我会将其动态转换为该类型。如果它返回 null,那么我知道它不是。
假设我们有一个我们正在使用的库,它旨在让我们从中派生一些类型:
class A {};
class B : public A {};
class C : public B {};
当我们派生我们的类型时,我们有一些对所有案例都通用的东西:
class CommonStuff {};
class D : public CommonStuff, public C {};
现在,当我们使用我们的库时,有一个回调类型为 A&(或 B& 或 C&)
void some_func(A& obj);
并假设在该函数中它期望多态行为,但我们需要访问我们的一些 CommonStuff:
void some_func(A& obj)
{
CommonStuff& comn = dynamic_cast<CommonStuff&>(obj);
}
由于 A 和 CommonStuff 之间没有直接关联,我们不能使用static_cast
,reinterpret_cast
显然不是正确的选择,因为它会引入切片。这里唯一的选择是dyanmic_cast
.
现在,把它和一粒盐放在一起,因为这可以解决。
您通常可以通过向 A 添加虚函数来替换 dynamic_cast<A*>(...)。但是,如果 A 是第三方库中的类,那么您无法更改它,因此您无法添加虚函数给它。所以你可能不得不使用dynamic_cast。