c++中强制指针类型转换

很多人啊 发布于 2013/05/15 21:25
阅读 295
收藏 1

我在cocox2d-x中有这样的代码:

class BaseEnity

{

public:

int m_type;

};


还有个叫做bullet的类,生于Baseenity类和一个CCSprite类。

我在主进程里实例化了bullet类,并把m_tag设置为0。

并将其指针加到了box2d中的一个 void*  成员内。

然后下面便出现问题了:

(BaseEnity*)(bulletBody->GetUserData())->m_type;

这行代码获取的m_type不是0,是一个随机数!!

但是当我这样写:

(BaseEnity*)(Bullet*)(bulletBody->GetUserData())->m_type;

或者:

(Bullet*)(bulletBody->GetUserData())->m_type;

却能得到正确的数值0.。

//getuserdata函数定义如下:inline void* b2Body::GetUserData() const

{   return m_userData;
}


我加个图片,有vs的调试信息。

加载中
0
平原君
平原君

这个建议看下《深入C++对象模型》这本书,里面有讲解。具体还是很复杂的,尤其又涉及到多继承。

0
小耶果
小耶果
涉及到继承类的转型推荐用dynamic_cast,...等C++特有的指针转换关键字.
0
stxy0509
stxy0509

关键就是bullet类继承于2个基类(假设为A和B),这2个基类的排列顺序与你想象的不一致。

可能是AB,也可能是BA。你想通过bullet *来获得基类地址,A或者B中有一个不需要地址变换,另一个必须要地址变换。

m_userData的类型是bullet *,当你通过(Bullet*)来完成转换时,编译器帮你正确完成了相关调整,但是当你想直接转换时,你想得到A的地址,或许得到的是B的地址。

0
adler
adler

你可以了解下C++对象切割和C++内存布局

0
狼来了而已
狼来了而已
你把 BaseEnity放在继承的最前面
0
adler
adler

下午刚好没事,帮你写个测试程序你可以看看:

#include <iostream>

using namespace std;

class Base
{
    public:
        char mBase;
    public:
        Base():mBase(1){}
        void function(){cout<<"class Base function"<<endl;}
        ~Base(){}
};
class Base_1
{
    public:
        int mBase_1;
    public:
        Base_1():mBase_1(555){}
        ~Base_1(){}
};
class Son:public Base,public Base_1
{
   public:
        int mSon;
    public:
        Son():mSon(1){}
        void function(){cout<<"class Son function"<<endl;}
        ~Son(){}
};
int main()
{
    Son* mySon=new Son();
    void* ptr;
    Base_1* p;
    ptr=(void*)mySon;//强制转换为void类型
    p=(Base_1*)ptr;//强制转换为Base_1类型
    cout<<p->mBase_1<<endl;

    mySon=(Son*)p;
    delete(mySon);
    return 0;
}
输出为:373553.显然错误。例子比较简单,这个特殊情况,可以通过调整继承顺序使输出恰好正确。因为如果你的子类和父类中包含有虚函数,那么你的输出就没那么恰好了。其实最主要还是要了解下C++的内存布局
0
match5
match5

这个建议不用多继承 通常的做法是:  BaceEnity继承自CCNode  所有游戏对象都继承自BaceEnity就行了 具体的Bullet应该有个CCSprite的成员 同时把这个sprite作为子节点加上

尽量不要同时继承自2个以上的非纯虚类

返回顶部
顶部