我对C ++很陌生,但多年来一直使用C#,但它并没有帮助我! :)
我的问题:我有一个Actor
课程,Ball
和Peg
都来自我正在开发的客观智能手机游戏。在我测试碰撞时,我希望根据Ball
或Peg
的实际运行时类型适当地设置actorA
和actorB
的实例。我的代码测试如下:
// Actors that collided
Actor *actorA = (Actor*) bodyA->GetUserData();
Actor *actorB = (Actor*) bodyB->GetUserData();
Ball* ball;
Peg* peg;
if (static_cast<Ball*> (actorA)) { // true
ball = static_cast<Ball*> (actorA);
}
else if (static_cast<Ball*> (actorB)) {
ball = static_cast<Ball*> (actorB);
}
if (static_cast<Peg*> (actorA)) { // also true?!
peg = static_cast<Peg*> (actorA);
}
else if (static_cast<Peg*> (actorB)) {
peg = static_cast<Peg*> (actorB);
}
if (peg != NULL) {
[peg hitByBall];
}
设置ball
和peg
后,我继续运行hitByBall
方法(目标c)。
我的问题真正存在的地方在于投射程序Ball
从actorA
投射得很好;第一个if (static_cast<>)
语句介入并适当地设置ball
指针。
第二步是将适当的类型分配给peg
。我知道peg
应该是Peg
类型,之前我知道它将是actorB
,但是在运行时,检测到类型,我很惊讶地发现第三个if (static_cast<>)
声明介入并设置了这个,这个if语句用于检查actorA
是否为Peg
,我们已经知道actorA
是Ball
!为什么它会在这里而不是在第四个if
声明中?
我唯一可以假设的是,如何使用与c#不同的方式,并且它发现实际属于actorA
的{{1}}派生自Ball
,然后在Actor
时找到执行{1}} static_cast<Peg*> (actorA)
Peg
也来自Actor
,这是一个有效的测试?这可能都归结为我误解了static_cast
的用法。我怎样才能达到我的需要? :)
我真的很不安,对我来说就像是一场长篇大论的蛮力尝试,在这里有大量荒谬的if
陈述。我确信有一种更优雅的方式来实现对Peg
的简单转换,并转换为Ball
,具体取决于actorA
和actorB
中的实际类型。
希望有人可以提供帮助! :) 非常感谢。
答案 0 :(得分:3)
由于这是Objective-C代码(不是C ++,根据标题),为什么不直接调用:
[actorA hitByBall];
[actorB hitByBall];
已更新:如果您要发送邮件的对象为nil
,则会被忽略。如果您发送消息的对象未实现hitByBall
,您将获得异常,“选择器无法识别”,除非您在基类(Actor
)中放置了一个空的定义。 / p>
然后,您可以删除ball
和peg
声明以及所有static_cast
声明(即使在C ++中也不正确)。
答案 1 :(得分:2)
要在运行时识别对象类型,您应该dynamic_cast
而不是static_cast
。但你应该重新考虑你的设计。可能(我没有关于objective-c的任何内容)你应该在基类中使hitByBall
成为虚方法,并在派生类中需要时覆盖实现。然后你可以在没有任何强制转换的情况下调用该方法。
答案 2 :(得分:1)
看来你正在寻找-isKindOfClass
。如果两个对象都符合NSObject协议,则只需要检查哪个类型 - 实际的消息传递不受指针的静态类型的限制:
if ( [actorA isKindOfClass:[Peg class ]]
&& [actorB isKindOfClass:[Ball class]])
{
[actorA hitByBall];
}
else if ( [actorB isKindOfClass:[Peg class ]]
&& [actorA isKindOfClass:[Ball class]])
{
[actorB hitByBall];
}