天天看點

【玩轉cocos2d-x之十九】從CCObject看cocos2d-x的拷貝機制

原創作品,轉載請标明:http://blog.csdn.net/jackystudio/article/details/13295505

CCObject在之前的文章中出現了N次,它扮演了一個老祖宗的角色,但是它到底是做什麼的?先從它看看cocos2d-x的拷貝機制吧。

1.CCCopying

CCObject從CCCopying繼承而來,而CCCopying擁有唯一的一個成員虛函數copyWithZone,這個函數可以認為是拷貝的一個協定,所有繼承了CCObject并且需要實作拷貝功能的子類都可以通過它來實作,它的源碼很簡單,就是一個未實作的斷言。CCZone是神馬?隻是封裝了一個CCObject對象指針而已。

CCObject* CCCopying::copyWithZone(CCZone *pZone)
{
    CC_UNUSED_PARAM(pZone);
    CCAssert(0, "not implement");
    return 0;
}           

2.CCObject的子類拷貝問題

再看看CCObject中copy的實作,是的,直接調用了copyWithZone,是以子類在處理拷貝問題時隻需要對copyWithZone進行實作,使用時調用copy即可。

CCObject* CCObject::copy()
{
    return copyWithZone(0);
}           

3.CCArray示例

這裡以CCArray的拷貝為例,CCArray繼承于CCObject,如上所說,我們隻需要實作copyWithZone,然後在拷貝時調用copy即可實作CCArray的拷貝。

3.1.CCArray拷貝時調用copy

CCArray* CCArray::createWithArray(CCArray* otherArray)
{
    CCArray* pRet = (CCArray*)otherArray->copy();//copy調用了copyWithZone
    pRet->autorelease();
    return pRet;
}           

3.2.copyWithZone的實作

可以看出CCArray采用的是深拷貝的方式。

CCObject* CCArray::copyWithZone(CCZone* pZone)
{
    CCAssert(pZone == NULL, "CCArray should not be inherited.");
    CCArray* pArray = new CCArray();  //new一個存放拷貝的空間
    pArray->initWithCapacity(this->data->num > 0 ? this->data->num : 1);//初始化一樣的長度

    CCObject* pObj = NULL;
    CCObject* pTmpObj = NULL;
    CCARRAY_FOREACH(this, pObj)//周遊CCArray成員
    {
        pTmpObj = pObj->copy();//逐個拷貝
        pArray->addObject(pTmpObj);//添加到新拷貝pArray中
        pTmpObj->release();
    }
    return pArray;//傳回拷貝
}           

4.深拷貝和淺拷貝

其實不單是CCArray,cocos2d-x采用的都是深拷貝的方式,深拷貝和淺拷貝的概念和詳解請移步http://blog.csdn.net/jackystudio/article/details/11553117。它們的差別在于目前對象是否包含了對其他資源的引用。在拷貝機制上采用深拷貝的方式,大大友善了我們對記憶體的管理,避免因資源的釋放導緻引用異常。這對于平時在進行一些自定義子類的拷貝處理上還是很有指導意義的。