先看一段代码如何在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

类定义成了这个样子:

  1. class GemBoard : public CCSprite, CCTargetedTouchDelegate

然后注册touch消息的时候

  1. 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

所以改成

  1. 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分析的更多相关文章

  1. android中的返回键与Activity

          我在做应用时遇到一个问题.就是在启动主页面时须要预先载入一些数据.我是在一个载入页中处理完这些数据然后再转到主页面.但当我在主页面中按返回键时,系统会返回载入页面.我不希望载入页在使用完之 ...

  2. 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 ...

  3. Android 中 appcompat_v7与各类资源报错问题

    最近导一个项目进eclipse弄了一天都弄不好,先总结如下 首先按照网上其他同志的导入sdk/extras下的appcompat_v7项目.然后 发现 我们这里已经更新到6.0了,也就是说,我们报错的 ...

  4. Android studio中的一次编译报错’Error:Execution failed for task ':app:transformClassesWithDexForDebug‘,困扰了两天

    先说下背景:随着各种第三方框架的使用,studio在编译打包成apk时,在dex如果发现有相同的jar包,不能创建dalvik虚拟机.一个apk,就是一个运行在linux上的一个虚拟机. 上图就是一直 ...

  5. nuxtjs在vue组件中使用window对象编译报错的解决方法

    我们知道nuxtjs是做服务端渲染的,他有很多声明周期是运行在服务端的,以及正常的vue声明周期mounted之前均是在服务端运行的,那么服务端是没有比如window对象的location.navag ...

  6. Python2在Sublime Text3中print中文时编译报错解决办法

    如果是用记事本新建的python文件,有可能是由于记事本默认的ascii格式导致的,这个时候只需要在Sublime Text3中   文件->设置文件编码(utf-8),保存即可.这样能够解决的 ...

  7. Linux程序设计中的curses.h编译报错,无法找到curses.h和ncurses.h

    源程序screen.c如下: #include <stdio.h> #include <term.h> #include <curses.h> #include & ...

  8. PopupWindow响应返回键的问题

    假设情景是这样的:在一个Activity中弹出一个PopupWindow,要求在按返回键时关闭该PopupWindow. 如果该PopupWindow是无焦点的(默认情况),那么可以在Activity ...

  9. Fragment响应返回键

    Activty可以直接响应返回键,而Fragment却不行,可用如下方式: 创建一个抽象类BackHandledFragment,该类中有一个抽象方法onBackPress(),所有BackHandl ...

随机推荐

  1. UVa 156 Ananagrams

    题意:给出一些单词,在这些单词里面找出不能通过字母重排得到的单词(判断的时候不用管大小写),然后按照字典序输出. 学习的紫书的map= = 将每一个单词标准化 先都转化为小写,再排序(即满足了题目中说 ...

  2. BZOJ 1076 奖励关

    注意几点: 1.为什么要逆推?由此状态可以轻易算出彼状态是否可行,而彼状态却无法轻易还原为此状态. 2.为什么可以逆推?假设时光倒流了....23333 3.注意位运算的准确,大胆写方程. #incl ...

  3. 20160203.CCPP体系详解(0013天)

    程序片段(01):数组.c+02.数组初始化语法.c 内容概要:数组 ///01.数组.c #include <stdio.h> #include <stdlib.h> //0 ...

  4. 搭建 MPICH3 并行计算环境

    先记录在单机MacBook上的搭建,实验室集群的搭建流程是一样的,不过每台机器都需要做一次. MacBook: 1.安装mpich3: $ ./configure --prefix=/Users/xi ...

  5. Android Studio你不知道的调试技巧

    写代码不可避免有Bug,通常情况下除了日志最直接的调试手段就是debug:那么你的调试技术停留在哪一阶段呢?仅仅是下个断点单步执行吗?或者你知道 Evaluate Expression, 知道条件断点 ...

  6. mate代码详解

    1.用以说明生成工具(如MICROSOFT FRONTPAGE 4.0)等: 2.向搜索引擎说明你的网页的关键词: 3.告诉搜索引擎你的站点的主要内容: 4.告诉搜索引擎你的站点的制作的作者: 5. ...

  7. 利用命令控制台cmd进入某个硬盘的某个文件夹的命令是什么?

    在命令行窗口中输入F:后回车就可以切换到F盘,如果想查看F盘的内容,可以再输入dir后回车 (输入“F”后要再输入一个“ :”再回车才行哦)

  8. UIView动画学习笔记

    UIView的动画是通过修改控件的属性来达到动画的效果,如:渐变, 移动. 废话不多说,直接上代码: - (void)loadView{ [super loadView]; _leftView = [ ...

  9. 使用 Google Fonts 为网页添加美观字体

    前言 文字是网页中很重要的组成部分.为文字选择一个合适的字体,能够更好的展现一个网站的个性,表达所要传递的信息,同时吸引用户来产生兴趣. 说到字体,我们首先会想到 CSS 里面的 font,例如: & ...

  10. UML系列图------用例图介绍

    UML-Unified Model Language 统一建模语言,又称标准建模语言.是用来对软件密集系统进行可视化建模的一种语言. 在UML系统开发中有三个主要的模型: 功能模型: 从用户的角度展示 ...