Cocos2d-x基礎:CCObject


    當時被問到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++基礎內容)


有問題的地方希望能回覆我~





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章