在C ++中转换为派生类型问题

时间:2010-05-22 04:12:01

标签: c++ objective-c casting box2d-iphone

我对C ++很陌生,但多年来一直使用C#,但它并没有帮助我! :)

我的问题:我有一个Actor课程,BallPeg都来自我正在开发的客观智能手机游戏。在我测试碰撞时,我希望根据BallPeg的实际运行时类型适当地设置actorAactorB的实例。我的代码测试如下:

// 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];
        }

设置ballpeg后,我继续运行hitByBall方法(目标c)。

我的问题真正存在的地方在于投射程序BallactorA投射得很好;第一个if (static_cast<>)语句介入并适当地设置ball指针。

第二步是将适当的类型分配给peg。我知道peg应该是Peg类型,之前我知道它将是actorB,但是在运行时,检测到类型,我很惊讶地发现第三个if (static_cast<>)声明介入并设置了这个,这个if语句用于检查actorA是否为Peg,我们已经知道actorABall!为什么它会在这里而不是在第四个if声明中?

我唯一可以假设的是,如何使用与c#不同的方式,并且它发现实际属于actorA的{​​{1}}派生自Ball,然后在Actor时找到执行{1}} static_cast<Peg*> (actorA) Peg也来自Actor,这是一个有效的测试?这可能都归结为我误解了static_cast的用法。我怎样才能达到我的需要? :)

我真的很不安,对我来说就像是一场长篇大论的蛮力尝试,在这里有大量荒谬的if陈述。我确信有一种更优雅的方式来实现对Peg的简单转换,并转换为Ball,具体取决于actorAactorB中的实际类型。

希望有人可以提供帮助! :) 非常感谢。

3 个答案:

答案 0 :(得分:3)

由于这是Objective-C代码(不是C ++,根据标题),为什么不直接调用:

[actorA hitByBall];
[actorB hitByBall];

已更新:如果您要发送邮件的对象为nil,则会被忽略。如果您发送消息的对象未实现hitByBall,您将获得异常,“选择器无法识别”,除非您在基类(Actor)中放置了一个空的定义。 / p>

然后,您可以删除ballpeg声明以及所有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];
}