Cocos2d-x基础:CCObject

本文介绍了Cocos2d-x中CCObject类的基础知识,包括其作为复制协议的角色、引用计数机制、内存自动管理以及autorelease()方法的使用。通过分析CCObject的构造函数和析构函数,阐述了如何在Cocos2d-x中实现对象的生命周期管理和多处引用的处理。同时提到了CCObject的acceptVisitor方法和update方法的基本作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


    当时被问到CCNode、CCObject、CCScene、CCACtion等是干什么用的、有什么意义时我不知道,只是初略的看过一些而已。


      由于我只大致看过一些资料,看了些Test工程而已,这些源码当时觉得暂时没必要看,实际的开发中会慢慢接触到。现在知道我做错了,如果在使用一个技术之前,不好好了解技术原理,就是非常坑爹的事情!

      废话完了,希望和同学们一起好好分析这个类,达到举一反三,甚至一劳永逸的效果,如有分析错误的地方,希望哪位同学帮我立刻指出来,多谢!

---------------------------------------------------------------------------------------------

      编程环境:Visual Studio 2010

      Coco版本:cocos2d-x-2.1.4

---------------------------------------------------------------------------------------------


      在CCObject.h中定义了两个类:CCCopying、CCObject。

class CC_DLL CCCopying
{
public:
    virtual CCObject* copyWithZone(CCZone* pZone);
};

      CC_DLL是一个宏定义,它使得类的输出为DLL,定义如下:

#define CC_DLL     __declspec(dllexport)

      总得来说,它是一个协议形式的类,继承于它的类都能够进行复制。

      接着回来看CCObject:

class CC_DLL CCObject : public CCCopying
{
public:
    // object id, CCScriptSupport need public m_uID
    unsigned int        m_uID;
    // Lua reference id
    int                 m_nLuaID;
protected:
    // count of references
    unsigned int        m_uReference;
    // count of autorelease
    unsigned int        m_uAutoReleaseCount;
public:
    CCObject(void);
    virtual ~CCObject(void);
    
    void release(void);
    void retain(void);
    CCObject* autorelease(void);
    CCObject* copy(void);
    bool isSingleReference(void) const;
    unsigned int retainCount(void) const;
    virtual bool isEqual(const CCObject* pObject);

    virtual void acceptVisitor(CCDataVisitor &visitor);

    virtual void update(float dt) {CC_UNUSED_PARAM(dt);};
    
    friend class CCAutoreleasePool;
};

      大致看一下,然后我们逐个深入CCObject的方法(函数方法是同一个东东,以后不再说明^ ^)实现。

      不是所有内容都需要分析,就好比方学习C++一样,C++之父说过“用到哪学到哪”。

CCObject构造函数:

CCObject::CCObject(void)
: m_nLuaID(0)
, m_uReference(1) // when the object is created, the reference count of it is 1
, m_uAutoReleaseCount(0)
{
    static unsigned int uObjectCount = 0;

    m_uID = ++uObjectCount;
}

      上面的构造函数中,主要是设置引用计数的计数器为1。什么,不知道引用计数干嘛用的?它解决了对象被多处地方引用时的管理方法。

      在程序的生命周期内,当两处及两处以上地方在使用此对象时,你无法判断内存中的对象何时应该被释放。如果不使用此对象,则调用对象的release方法,计数器会减1。如果计数器的值为0,那么这个对象才会从内存中,被释放掉(最后一个地方release时,就会delete对象)。

void CCObject::release(void)
{
    CCAssert(m_uReference > 0, "reference count should greater than 0");
    --m_uReference;

    if (m_uReference == 0)
    {
        delete this;
    }
}
      上面的release方法可以看到每次调用此方法时,m_uReference就会减1,直到m_uReference为0。

      既然说到这里,我们初学C++或Cocos2d-x的同学肯定有个疑惑:怎么才能再多个地方使用对象?

      答:指针传递。

      指针传递之后,就多处地方使用了这个内存对象,那从哪里增加引用计数的值?(内存对象的说法比对象更贴近实际,以后不解释;) )

      答:这就是retain()方法的由来咯,使用retain方法,m_uReference就会增1。当传递对象指针时,首先调用retain()方法,然后再赋值地址。

      示例代码如下:

void func(CCObject *obj)
{
    ojb->retain();
    ojb->release();
    CCObject *pObj = obj;
    ...
    ...
    pObj->release();
}

      CCObject析构函数:

CCObject::~CCObject(void)
{
    // if the object is managed, we should remove it
    // from pool manager
    if (m_uAutoReleaseCount > 0)
    {
        CCPoolManager::sharedPoolManager()->removeObject(this);
    }

    // if the object is referenced by Lua engine, remove it
    ....
}
      由于Cocos2d-x里有自己的内存自动管理机制,所以我们在清除对象的时候也可以不用去手动的清除(delete xxx),前提是使用了release,或autorelease。

      析构函数里只是做售后处理而已,当内存对象被释放时,也应该从内存池中删除引用。

      上面我们知道,引用计数用来解决多处地方使用对象时的内存释放问题。

      下面通过CCObejct类,我们来看Cocos2d-x是如何实现自动管理内存的。

      创建了对象之后,如果不想手动清除对象,那就使用autorelease()方法。每帧结束后,会自动释放对象。

CCObject* CCObject::autorelease(void)
{
    CCPoolManager::sharedPoolManager()->addObject(this);
    return this;
}
void CCPoolManager::addObject(CCObject* pObject)
{
    getCurReleasePool()->addObject(pObject);
}
void CCAutoreleasePool::addObject(CCObject* pObject)
{
    m_pManagedObjectArray->addObject(pObject);

    CCAssert(pObject->m_uReference > 1, "reference count should be greater than 1");
    ++(pObject->m_uAutoReleaseCount);
    pObject->release(); // no ref count, in this case autorelease pool added.
}

      上面代码的逻辑较严格。

      (1)m_pManagedObjectArray->addObject(pObject),一开始把对象添加到内存管理的队伍中(此时就有了两处地方使用了此对象)。

      (2)断言对象的引用数是否大于1。

      (3)释放对象。

    总结一下CCObject:

      1、提供了引用计数机制。

      2、提供了内存自动管理机制的入口。

      3、提供了复制对象的能力。

      4、在这个版本里,有acceptVisitor(CCDataVisitor &visitor)方法,头文件中是这样说明的:

          Visitor that helps to perform action that depends on polymorphic object type.

           意思就是,这个类辅助去执行Action,Action动作取决于多态对象的类型。就是允许对象使用动作,不深入,以后看。

      5、update()方法,因为它主要是被继承使用,在此没有作用。

      6、CCAutoreleasePool的友元类的作用是让CCAutoreleasePool可以访问此类的私有区域。(C++基础内容)


有问题的地方希望能回复我~





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值