【问题标题】:Not able to call method after typecasting to base class类型转换为基类后无法调用方法
【发布时间】:2026-01-23 05:10:02
【问题描述】:

我有 Ball 类,它派生自 PhysicsObject 类。在以下方法中,我从void 指针获取Ball 实例并检查其类型是否为PhysicsObject。当我调用collidingWith 方法时,它不会在Ball 类对象中被调用。我在这里做错了什么?

更新 我在底部添加了sscce。请参考。

代码

void Levels::BeginContact(b2Contact *contact) {
    b2Fixture *fixtureA = contact->GetFixtureA();
    b2Fixture *fixtureB = contact->GetFixtureB();
    void *objA = fixtureA->GetUserData();
    void *objB = fixtureB->GetUserData();

    PhysicsObject* physicsObjA = reinterpret_cast<PhysicsObject*>(objA);
    PhysicsObject* physicsObjB = reinterpret_cast<PhysicsObject*>(objB);
    if ((physicsObjA != 0) && (physicsObjB != 0)) {
        physicsObjA->collidingWith(physicsObjB);    //not working
        physicsObjB->collidingWith(physicsObjA);
    }
}

物理对象

#ifndef PHYSICSOBJECT_H_
#define PHYSICSOBJECT_H_

class PhysicsObject {
public:
    PhysicsObject();
    virtual ~PhysicsObject();

    virtual void collidingWith(PhysicsObject *obj) = 0;
};

#endif /* PHYSICSOBJECT_H_ */

球.h

#ifndef BALL_H_
#define BALL_H_

#include "Box2D/Box2d.h"
#include "cocos2d.h"
#include "PhysicsObject.h"

class Ball : public PhysicsObject {
public:
    //other methods
    void collidingWith(PhysicsObject *obj);
};

#endif /* BALL_H_ */

球.cpp

void Ball::collidingWith(PhysicsObject *obj) {
    CCLOG("Ball::collidingWith"); //this method is not being called
}
 //other methods

Ball::Ball() {
    //other code
    b2FixtureDef ballShapeDef;
    ballShapeDef.userData = this;
    //other code
}

更新 我还有 3-4 个其他类是从 PhysicsObject 派生的,就像 Ball 一样,我在这里没有提到,但通用代码是相同的。

更新 SSCCE
main.cppfoo()baseObjA-&gt;collidingWith(baseObjA); 出现错误

基类

class Base
{
public:
    Base(void);
    virtual ~Base(void);
    virtual void collidingWith(Base *obj) = 0;
};

另一个基类

class AnotherBase
{
public:
    AnotherBase(void);
    ~AnotherBase(void);
    virtual void foo();
};

派生类头

#include "Base.h"
#include "AnotherBase.h"
class Derived :
    public AnotherBase, Base
{
public:
    Derived(void);
    ~Derived(void);
    void collidingWith(Base *obj);
};

派生类实现

#include "Derived.h"

void Derived::collidingWith(Base *obj) {
    printf("Ball::collidingWith");
}

ma​​in.cpp

#include "Derived.h"

void myFoo(void* userData);
int _tmain(int argc, _TCHAR* argv[])
{
    Derived *derived = new Derived();
    void* userData = derived;
    myFoo(userData);
    return 0;
}

void myFoo(void* userData) 
{
    Base* baseObjA = reinterpret_cast<Base*>(userData); 
    if (baseObjA != 0) {
        baseObjA->collidingWith(baseObjA);// Error here
    }
}

【问题讨论】:

  • 你试过投射到Ball吗?
  • @AdriC.S.不,我没有,实际上我需要这种方式,因为还有其他类,如 Ball 派生自 PhysicsObject
  • 你怎么知道是Ball?球从哪里来?如果您将Ball 分配给PhysicsObject,您可能已经对其进行了切片。
  • 你能提供sscce吗?
  • 您是否 100% 确定 GetUserData() 调用实际上返回了指向 PhysicsObject 的指针?

标签: c++ inheritance casting box2d cocos2d-x


【解决方案1】:

在 box2d 中从 void* 铸造也给了我非常相似的问题。

似乎reinterpret_cast 会导致错误,因为collidingWith 是一个虚拟方法。 (如果方法不是虚拟的,你应该可以毫无问题地调用它)。

我已经解决了这个问题:

void* data; // You know it's type is Base

Base* base = static_cast<Base*>(data);
Derived* derived = dynamic_cast<Derived*>(base);

derived->collidingWith();

【讨论】:

  • 你能投票吗?如果您需要,我会添加更多解释:)
最近更新 更多