今天在安装网上的教程写塔防小游戏的时候遇到一点问题,原文中是用cocos 3.X的代码写的,而由于我用的是2.X(破电脑编译3.X速度实在难以忍受),所以很多小地方都需要修改。
其中有一个3.X新加的Vector(Node*)类型,我在2.X里找不到对应的类型,以为跟std::vector(CCNode*)应该差不多,所以就直接替代着用了,编译倒是没有报错,可是每次一运行就GG了。后来发现原来是std::vecor保存的指针对应的内存在运行时被自动释放了,猜测估计是Vector类型会自动对内存进行retain操作。于是换个类型,想着用Cocos自带类型或许会好点,所以就改为CCArray,没想到还是同样的问题。上网一查,果然CCArray被其他类引用的时候并不会自动增加引用值,需要手动retain,于是在引用的时候调用retain(),析构的时候调用release(),解决问题。
我是分隔符///
上面是用的浅拷贝的方法,今天突然想到或许用深拷贝会更好,于是找到了CCArray中有这样一个函数CreateWithArray(),马上动手试了一下,没想到又遇到了各种报错。深入查看源码发现,这个函数调用的是基类的copy函数。部分代码如下:
CCObject* CCObject::copy()
{
return copyWithZone(0);
}
CCObject* CCCopying::copyWithZone(CCZone *pZone)
{
CC_UNUSED_PARAM(pZone);
CCAssert(0, "not implement");
return 0;
}
CCArray* CCArray::createWithArray(CCArray* otherArray)
{
CCArray* pRet = (CCArray*)otherArray->copy();
pRet->autorelease();
return pRet;
}
CCObject* CCArray::copyWithZone(CCZone* pZone)
{
CCAssert(pZone == NULL, "CCArray should not be inherited.");
CCArray* pArray = new CCArray();
pArray->initWithCapacity(this->data->num > 0 ? this->data->num : 1);
CCObject* pObj = NULL;
CCObject* pTmpObj = NULL;
CCARRAY_FOREACH(this, pObj)
{
pTmpObj = pObj->copy();
pArray->addObject(pTmpObj);
pTmpObj->release();
}
return pArray;
}
可以看到基类CCObject中对copy只是做了简单的报错处理,而实际运行的时候调用的是CCArray中重新写的虚函数copyWithZone,这看起来似乎没什么问题,在copyWithZone中重新开辟了内存并把成员也复制过来,都是深拷贝,但是我运行的时候还是报错了。原来是因为我的CCarray装的是CCNode对象,而我看了一下CCNode类的源代码,发现CCNode中并米有对copyWithZone函数进行重写,所以复制成员的时候调用的是基类的中函数,所以报错。