[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier]
红孩儿Cocos2d-X学习园地QQ群:249941957 [暂满]加群写:Cocos2d-x
红孩儿Cocos2d-X学习园地QQ2群:44208467加群写:Cocos2d-x
Cocos2d-x 的CCObject与autorelease 之深入分析
在上一节“Cocos2d-x 2.0 TestCpp框架源码分析”中,我们深入分析了TestController类的实现。其中我们曾经遇到这两句代码:
//新创建一个TestController对象
CCLayer* pLayer = newTestController();
//将它交由内存管理器进行内存释放管理
pLayer->autorelease();
在创建了一个TestController实例对象后,对它调用了autorelease函数。这个该怎么理解这一句的含义呢?我们先来看一下基类CCObject是怎么定义的。
读前小提示:CCScriptEngineManager是脚本引擎管理器,它对于使用的脚本引擎进行管理。说起脚本引擎,首先要了解什么是脚本?脚本是使用特定的语言格式来编写的描述一定逻辑功能的文本文件,它可以实现在文本文件中通过访问特定格式的函数对系统逻辑进行编程。这个文本文件不被编译进可执行程序中,而是动态的在需要的时候通过系统对这个文本文件的解释来执行。脚本引擎则可以理解为对脚本的使用管理进行封装的相关的类和接口函数。游戏中常用的脚本有Lua和Python。目前Cocos2d-x集成了Lua的脚本引擎模块,使用非常方便。后面的Lua章节我们进行详细讲解。
读前小提示:引用计数器是一种内存管理方式。通过一个无符号的成员变量计算当前有多少使用者在使用本内存。每次外部对象使用本内存时计数器加1,使用完要释放本内存时计数器减1,当计数器减为0时才真正进行占用内存释放。这样做可以实现在多个使用者使用一块内存时,只有当所有的使用者都确定不再使用这块内存的时候才进行内存的释放。避免了在还有使用者在使用内存时提前释放内存而导致的程序崩溃。
重点函数:release()
- #ifndef__CCOBJECT_H__
- #define__CCOBJECT_H__
- #include"platform/CCPlatformMacros.h"
- //Cocos2d命名空间
- NS_CC_BEGIN
- //声明以下几种类,在后面会定义相应类的成员变量的指针。以下几个类均是CCObject类的派生类。
- classCCZone;//CCObject指针暂存类
- classCCObject;//基类
- classCCNode;//结点类
- classCCEvent;//事件类
- //这里定义了一个拷贝类
- classCC_DLLCCCopying
- {
- public:
- //虚函数。功能是为CCZone指针所指向的对象复制一份新的CCObject对象指针
- virtualCCObject*copyWithZone(CCZone*pZone);
- };
- //由CCCopying派生出CCObject
- classCC_DLLCCObject:publicCCCopying
- {
- public:
- //唯一ID
- unsignedintm_uID;
- //在LUA脚本引擎中的访问标识ID.暂可不理会,待学习到LUA时再分析
- intm_nLuaID;
- protected:
- //引用计数器,进行内存计数。
- unsignedintm_uReference;
- //是否是被内存管理器进行托管而自动进行释放。
- boolm_bManaged;
- //构造函数
- CCObject(void);
- //析构函数
- virtual~CCObject(//释放
- voidrelease(//保留
- voidretain(//设置实例对象的释放由内存管理器进行管理。实现自动释放。
- CCObject*autorelease(//取得一个拷贝
- CCObject*copy(//本类的实例化对象是否只有一个使用者
- boolisSingleRefrence(//返回内存计数器的值,也就是取得使用者的个数
- intretainCount(//判断是否与另一个CCObject实例对象相同
- virtualboolisEqual(constCCObject*pObject);
- //更新函数
- virtualvoidupdate(ccTimedt){CC_UNUSED_PARAM(dt);};
- //设定CAutoreleasePool为友元类,这是一个通过CCObject指针容器CCMutableArray来对CCObject实例对象的内存进行管理的类,CCMutableArray在加入CCObject时对其引用计数器加1,在移除CCObject时对其引用计数器减1。
- friendclassCCAutoreleasePool;
- };
- //定义一些函数
- //定义定时器访问类成员函数
- typedefvoid(CCObject::*SEL_SCHEDULE)(ccTime);
- //定义普通回调类成员函数
- void(CCObject::*SEL_CallFunc)();
- //定义带结点参数的回调类成函数
- void(CCObject::*SEL_CallFuncN)(CCNode*);
- //定义带结点参数及1个用户值参数的回调类成员函数
- void(CCObject::*SEL_CallFuncND)(CCNode*,void*);
- void(CCObject::*SEL_CallFuncO)(CCObject*);
- //定义菜单响应类成员函数
- void(CCObject::*SEL_MenuHandler)(CCObject*);
- //定义事件响应类成员函数
- void(CCObject::*SEL_EventHandler)(CCEvent*);
- //定义一些宏来取得这些回调成员函数的指针。
- #defineschedule_selector(_SELECTOR)(SEL_SCHEDULE)(&_SELECTOR)
- #definecallfunc_selector(_SELECTOR)(SEL_CallFunc)(&_SELECTOR)
- #definecallfuncN_selector(_SELECTOR)(SEL_CallFuncN)(&_SELECTOR)
- #definecallfuncND_selector(_SELECTOR)(SEL_CallFuncND)(&_SELECTOR)
- #definecallfuncO_selector(_SELECTOR)(SEL_CallFuncO)(&_SELECTOR)
- #definemenu_selector(_SELECTOR)(SEL_MenuHandler)(&_SELECTOR)
- #defineevent_selector(_SELECTOR)(SEL_EventHandler)(&_SELECTOR)
- #definecompare_selector(_SELECTOR)(SEL_Compare)(&_SELECTOR)
- NC_CC_END
- #endif//__CCOBJECT_H_
CCObject.cpp:
- #include"CCObject.h"
- //内存管理器头文件
- #include"CCAutoreleasePool.h"
- //Cocos2d-x定义的一些宏的头文件
- #include"ccMacros.h"
- //加入脚本支持
- #include"scripte_support/CCScriptSupport.h"
- NS_CC_BEGIN
- //虚函数。这里简单处理一下。需要进行重载
- CCObject*CCCopying::copyWithZone(CCZone*pZone)
- CC_UNUSED_PARAM(pZone);
- //如果不进行重载,则会提示没有重载实现函数功能。
- CCAssert(0,"notimplement");
- return0;
- }
- //构造
- CCObject::CCObject(void)
- //定义一个静态UINT类型变量做为实例对象计数器,此值只会增长,不会减少,保证唯一。
- staticunsignedintuObjectCount=0;
- //将计数器加1后赋值给唯一ID。
- //注意:所有由此CCObject类派生的子类也会拥有这个唯一的ID。它可以使我们通过唯一ID来获取相应的实例对象。
- m_uID=++uObjectCount;
- //脚本ID
- m_nLuaID=0;
- //当类进行实例化时,将m_uReference设为1
- m_uReference=1;
- //初始化时设实例化对象由用户进行内存管理。如果new出一个对象,需要自行delete。
- m_bManaged=false;
- //析构
- CCObject::~CCObject( 如果内存是由内存管理器统一管理,则调用内存管理器实例对象的移除函数对自已的内存进行释放。
- if(m_bManaged)
- CCPoolManager::getInstance()->removeObject(this);
- //如果有使用到LUA脚本,调用脚本引擎的实例对象的移除函数将本身从脚本引擎的实例对象中移除。
- if(m_nLuaID)
- CCScriptEngineManager::sharedManager()->getScriptEngine()->removeCCObjectByID(m_nLuaID);
- }
- //返回一个本类实例化对象的拷贝
- CCObject*CCObject::copy()
- returncopyWithZone(0);
- //供使用者外部调用的释放函数
- voidCCObject::release(//先确保计数器是大于0的数值,说明正常有效
- CCAssert(m_uReference>0,"referencecountshouldgreaterthan0");
- //计数器减1
- --m_uReference;
- //如果计数器减为0,释放本类实例化对象占用的内存
- if(m_uReference==0)
- deletethis;
- //使用者外部调用的,使用一次时更新计数器。
- voidCCObject::retain(void)
- ++m_uReference;
- //设置当前类的实例化对象的内存管理交给内存管理器去管理,不手动进行内存计数器的处理。
- CCObject*CCObject::autorelease(//调用内存管理器实例对象的addObject函数加入当前CCObject实例对象的指针
- CCPoolManager::getInstance()->addObject(//打开使用内存管理器的标记
- true;
- returnthis;
- //是否当前类的实例化对象只被一个使用者使用
- boolCCObject::isSingleRefrence(//计数器的个数即代表使用者的个数,因为一个使用者使用一次,计数器加1
- returnm_uReference==1;
- //返回当前类的实例化对象的使用者的个数
- intCCObject::retainCount(returnm_uReference;
- //是否与另一个基类为CCObject的实例化对象是同一个对象
- boolCCObject::isEqual(constCCObject*pObject)
- this==pObject;
- NS_CC_END