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
类定义成了这个样子:
plaincopy
- class GemBoard : public CCSprite, CCTargetedTouchDelegate
然后注册touch消息的时候
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
所以改成
plaincopy
- class GemBoard : public CCSprite, public CCTargetedTouchDelegate
原文地址:http://blog.csdn.net/bill_ming/article/details/9352449
突然明白了,原来如此。赶紧看看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了
。
cocos2d-x在android中响应返回键编译报错的bug分析的更多相关文章
- android中的返回键与Activity
我在做应用时遇到一个问题.就是在启动主页面时须要预先载入一些数据.我是在一个载入页中处理完这些数据然后再转到主页面.但当我在主页面中按返回键时,系统会返回载入页面.我不希望载入页在使用完之 ...
- Android AS升级3.1 编译报错:The SourceSet 'instrumentTest' is not recognized by the Android Gradle Plugin.
AndroidStudio升级到3.1后编译报错:The SourceSet ‘instrumentTest’ is not recognized by the Android Gradle Plug ...
- Android 中 appcompat_v7与各类资源报错问题
最近导一个项目进eclipse弄了一天都弄不好,先总结如下 首先按照网上其他同志的导入sdk/extras下的appcompat_v7项目.然后 发现 我们这里已经更新到6.0了,也就是说,我们报错的 ...
- Android studio中的一次编译报错’Error:Execution failed for task ':app:transformClassesWithDexForDebug‘,困扰了两天
先说下背景:随着各种第三方框架的使用,studio在编译打包成apk时,在dex如果发现有相同的jar包,不能创建dalvik虚拟机.一个apk,就是一个运行在linux上的一个虚拟机. 上图就是一直 ...
- nuxtjs在vue组件中使用window对象编译报错的解决方法
我们知道nuxtjs是做服务端渲染的,他有很多声明周期是运行在服务端的,以及正常的vue声明周期mounted之前均是在服务端运行的,那么服务端是没有比如window对象的location.navag ...
- Python2在Sublime Text3中print中文时编译报错解决办法
如果是用记事本新建的python文件,有可能是由于记事本默认的ascii格式导致的,这个时候只需要在Sublime Text3中 文件->设置文件编码(utf-8),保存即可.这样能够解决的 ...
- Linux程序设计中的curses.h编译报错,无法找到curses.h和ncurses.h
源程序screen.c如下: #include <stdio.h> #include <term.h> #include <curses.h> #include & ...
- PopupWindow响应返回键的问题
假设情景是这样的:在一个Activity中弹出一个PopupWindow,要求在按返回键时关闭该PopupWindow. 如果该PopupWindow是无焦点的(默认情况),那么可以在Activity ...
- Fragment响应返回键
Activty可以直接响应返回键,而Fragment却不行,可用如下方式: 创建一个抽象类BackHandledFragment,该类中有一个抽象方法onBackPress(),所有BackHandl ...
随机推荐
- CMS 垃圾回收日志
CMS 垃圾回收日志 https://blogs.oracle.com/poonam/entry/understanding_cms_gc_logs http://www.blogjava.net/D ...
- URAL1352. Mersenne Primes
梅森素数 打表 搜梅森素数的时候 看到一句话 欧拉在双目失明的情况下 用心算出了2的31次方-1是素数 他用心算的... #include <iostream> #include<c ...
- 用HTML5 Canvas为网页添加动态波浪背景
查看所有代码请去Github 本文出自 “UED” 博客:http://5344794.blog.51cto.com/5334794/1430877 <!DOCTYPE html> < ...
- div中文字水平和垂直居中的css代码
HTML元素 <div>水平垂直居中</div> css样式 div{ width:200px;height:200px; /*设置div的大小*/ border:1px so ...
- Bundle对象的使用
在Android开发中,如果要通过一个Activity启动另外一个Activity,需要调用startActivity()函数,这个函数的参数是一个Intent对象,这个对象通常的初始化方式如下: I ...
- curl文件上传有两种方式,一种是post_fileds,一种是infile
curl文件上传有两种方式,一种是POSTFIELDS,一种是INFILE,POSTFIELDS传递@实际地址,INFILE传递文件流句柄! );curl_setopt($ch, CURLOPT_PO ...
- 计算机网络——TCP/IP协议族详解
一.OSI七层协议体系结构域TCP/IP四层体系结构对比 ISO/OSI模型,即开放式通信系统互联参考模型(Open System Interconnection Reference Model),是 ...
- C++类构造函数初始化列表
C++类构造函数初始化列表 构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class CExample {public: ...
- Web Developer可以做得更多
美国雅虎前端工程师Hedger Wang.这位原雅虎奇摩的第一位Web Developer,非常慷慨的与我们分享了他丰富的经验.现身说法,比空洞的理论更有感染力,我们发现现在遇到的很多问题也都是他曾经 ...
- jdbc操作数据库返回结果集的注意事项
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sq ...