cocos2d-x在android中响应返回键编译报错的bug分析
先看一段代码如何在Android中加入返回按键的响应
<span style="font-size:18px;">自己派生CCKeypadDelegate的子类,然后注册为键盘事件的委托调用class MyKeypadDelegate:public CCKeypadDelegate{public:virtual void keyBackClicked();virtual void keyMenuClicked();};m_pKeypadDlegate = new MyKeypadDelegate();pDirector->getKeypadDispatcher()->addDelegate(m_pKeypadDlegate);</span>
原帖:http://blog.csdn.net/lamp_zy/article/details/8210303
第一眼看到这段代码并没有什么问题,但是在自己在测试的时候却发现一个问题,运行报错。通过错误追踪发现了报错的地方。
在CCKeypadDelegate.cpp中有这么一段:
<span style="font-size:18px;"> bool CCKeypadHandler::initWithDelegate(CCKeypadDelegate *pDelegate) { CCAssert(pDelegate != NULL, "It's a wrong delegate!"); m_pDelegate = pDelegate; dynamic_cast<CCObject*>(pDelegate)->retain(); //这里 return true; }</span>
其中 dynamic_cast<CCObject *>(pDelegate)->retain();报错,报错的原因是pDelegate的引用计数为0。这就奇怪了,明明外部调用的地方已经赋值了。在考虑一下,想到了曾经看到的一篇文章:
CCTargetedTouchDelegate 的继承 和 dynamic_cast
想写个可以响应touch的sprite
类定义成了这个样子:
[cpp]view plaincopy- classGemBoard:publicCCSprite,CCTargetedTouchDelegate
然后注册touch消息的时候 [cpp]view plaincopy
- CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this,0,true);
在这挂了,查了一下午,挂在了
-addTargetedDelegate
-CCTargetedTouchHandler::handlerWithDelegate
-initWithDelegate
-CCTouchHandler::initWithDelegate
-dynamic_cast<CCObject*>(pDelegate)->retain();
-void CCObject::retain(void)
跟到这里,编译器告诉我CCObject的this指针是0,我晕呀。感觉太诡异了。
原因:CCTargetedTouchDelegate在上面的写法中是私有继承,而根据dynamic_cast的作用:(运算符可以在执行期决定真正的类型。如果downcast是安全的(也就说,如果基类指针或者引用确实指向一个派生类对象)这个运算符会传回适当转型过的指针。如果downcast不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。)上面的情况就合情合理了。
今天学到了2个知识点:
1.class B: public A, C 这种情况下A是public继承,C是private继承;class B: A这个A也是private继承
2.dynamic_cast 除了public 的其他都返回null
所以改成
[cpp]view plaincopy- classGemBoard:publicCCSprite,publicCCTargetedTouchDelegate
突然明白了,原来如此。赶紧看看CCKeypadDelegate.h文件的继承关系,源码如下:
<span style="font-size:18px;"> class CC_DLL CCKeypadDelegate //没继承 CCObject { public: // The back key clicked virtual void keyBackClicked() {} // The menu key clicked. only available on wophone & android virtual void keyMenuClicked() {}; };</span>
问题就出在这里,引擎尝试将CCKeypadDelegate 类型的指针转换成CCObject类型,但是CCKeypadDelegate 并没有继承 CCObject,所以dynamic_cast 运算后返回的是0,造成了程序中断退出
问题找到了那么就好解决了,一种网上比较流行的解决方式,修改cocos2d-x的源码,将这句话屏蔽掉。呵呵,虽然这是比较快捷的修改方式,但是为以后引擎升级和后续修改埋下了深深的隐患。所以这一种方式个人极不推荐。因此我们就要寻找新的解决方式。既然引擎是要将CCKepadDelegate强制转换为CCObject类型,而这个delegate又是我们自己定义的所以,我们只要将这个自定义的delegate继承CCObject就可以了,代码如下:
class MyKeypadDelegate:public CCKeypadDelegate,<span style="color:#FF0000;">public CCObject</span>{public:virtual void keyBackClicked();virtual void keyMenuClicked();};m_pKeypadDlegate = new MyKeypadDelegate();pDirector->getKeypadDispatcher()->addDelegate(m_pKeypadDlegate);
再次运行程序,一切OK了 。
更多相关文章
- Android打开本地相册选取图片并显示在ImageView上
- Android(安卓)不明确key时遍历JSONObject
- 环形进度条简单实现
- android APT 切换 annotationProcessor使用
- Android之如何获取网络类型并判断是否可用
- Android(安卓)面向对象编程 类与对象
- Android(安卓)触摸屏驱动代码分析(ADC 类型触摸屏 CPU:s3c-s5pc1
- Android变成setContentView()报错空指针异常
- Android(java)学习笔记91:泛型接口的概述和使用