类型转换为基类后无法调用方法

Posted

技术标签:

【中文标题】类型转换为基类后无法调用方法【英文标题】:Not able to call method after typecasting to base class 【发布时间】:2013-04-19 12:01:07 【问题描述】:

我有 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 一样,我在这里没有提到,但通用代码是相同的。

更新 SSCCEmain.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 的指针? 【参考方案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();

【讨论】:

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

以上是关于类型转换为基类后无法调用方法的主要内容,如果未能解决你的问题,请参考以下文章

无法将参数 1 从派生指针转换为基类指针引用

将派生类转换为基类

Part7 继承与派生 7.3基类与派生类类型转换

<继承问题>可以把基类对象赋值给子类对象么?

将指针从派生类转换为基类的最佳方法

将派生类转换为基类