自从Cocos2d-x3.0开始,Cocos2dx就正式的使用了C++11标准.C++11简洁方便的特性使程序的可拓展性和可维护性大大提高,也提高了代码的书写速度。

  下面我们就来一起学习一下Cocos2d-x开发中那些不得不了解的C++11知识。

 1.初始化列表

  POD结构或者数组根据成员在结构内定义的顺序,可以使用初始化列表来进行初始化以简化代码。

   

struct StructA{
int a;
int b;
}; StructA sa={,};

  在C++03中,非POD结构的类或者STL容器并不支持这种简便的写法,而C++11提供了强大的支持。使用std::initializer_list可以让类和普通函数使用初始化列表,并且STL容器也是可以使用初始化列表,代码如下:

//类使用初始化列表
class ClassA{
public:
ClassA(std::initializer_list<int>list){}
}; ClassA a = { , , }; /*注意!使用std::initializer_list需要先include <initializer_list>头文件*/
//函数使用初始化列表
void func(std::initializer_list<float>list){
/*Function Body*/
} func({1.6f,2.8f});
/*注意!使用std::initializer_list需要先include <initializer_list>头文件*/
//STL标准容器使用初始化列表
vector<string> s = {"hello","C++",""};

  可以看到在引入了std::initializer_list特性之后,初始化变量的工作简洁了许多,非常方便。

 2.自动类型推导

  类型推导可以在编译的时候自动来识别对象的类型,从而简化代码,更好的使用模版编程,使用auto关键字即可自动推导类型明确的变量,例如:

  

    /*自动类型推导*/
vector<int> v;
vector<int>::iterator it=v.begin(); //使用类型推导前
auto it2 = v.begin(); //使用类型推导后

  decltype也可以根据已有的对象自动识别类型,但是它和auto的不同之处是:auto是自动推导出表达式右边的类型,而decltype是自动推导出任意一个变量的类型,并且可以用该类型来定义变量,说起来比较难理解,看下面的代码就一目了然了:

  

    int num;
decltype(num) b = ;

 3.自动范围推导

  在C++11以前,写一个循环语句通常是这样的:

  

    for (int i = ; i < ; i++){            //使用自动范围推导前
cout << i << endl;
}

  而在C++11中,for语句新增了范围迭代的写法,该写法可以简化for循环的代码,“:”符号左边是要编历的元素类型,可以是引用或者const引用类型;而“:”右边是要编历的容器可以是数组或者STL容器等,代码如下:

  

    int arr []= { , , , ,  };      //使用自动范围推导后
for (int &i : arr){
cout << i << endl;
}

 4.智能指针和空指针

  智能指针是一个类而并非是普通的指针,shared_ptr是一引用计数指针,一个shared_ptr只有在已经没有任何其他shared_ptr指向其原本所指向的对象时,才会销毁该对象。

  除了shared_ptr之外,还有weak_ptr,但是weak_ptr并不拥有其所指向的对象,因此不影响该对象的销毁与否,也不能对weak_ptr解引用,只能判断该指针是否已经被销毁。下面举个例子说明一下shared_ptr:

  

    /*智能指针和空指针*/
//智能指针只能被智能指针赋值,不能用shared_ptr<int> pq= new int;
shared_ptr<int> p1(new int);
//用{ }进入一个新的作用域
{
//新的智能指针指向p1,这是相当于对int内存块的一次retain
shared_ptr<int> p2 = p1;
*p2 = ;
//p2被销毁,相当于对int内存块的一次release,但是由于p1还指向该内存,引用计数器不为0,因此不会释放
} return ;
//p1也被销毁,此时引用计数为0,int所占用的内存被自动回收 /*注意!使用shared_ptr需要include <memory>*/

  如果将share_ptr定义为类的成员变量,那么此智能指针的retain引用会在该对象被释放的时候才释放。

  空指针nullptr的存在是为了解决NULL的二义性问题,因为NULL也可以代表0,nullptr的类型为nullptr_t,能隐式转换为任何指针或者是成员指针的类型,也能和它们进行相等或者不等的比较。而nullptr不能隐式转换为整数,也不能和整数做比较。

  

    void foo(char *);
void foo(int);
foo(NULL); //调用的是void foo(int);
foo(nullptr); void foo(char *);

5.Lambda特性

  lambda表达式是一个非常好的新特性,当你需要在程序中添加一个新的临时函数时,直接使用Lambda函数,会让你感觉到原来写程序还可以这么爽~(类似于Java中的 匿名内部类)。lambda的写法如下:

  

[函数外部对象参数] (函数参数) -> 返回值类型{ 函数体}

  (1)[ ]中的函数外部对象参数,允许在函数体内直接调用函数外部的参数;

  (2)( )中的参数,同正常函数的参数没有什么差异,是每次函数调用时传入的变量;

  (3)->后面跟着函数返回值的类型;

  (4){ }里面可以编写逻辑函数,并使用[ ]和( )传入的参数

  定义在lambda函数相同作用域的参数引用也可以被使用,这种参数集合一般被称为闭包,[ ]中可以填写下面的几种类型的参数,将定义lambda函数作用域内的变量传入函数体中。

  1.[ ]可以没有任何参数,这种情况下不传入外部参数

  2.[a,&b]传入变量a的值以及变量b的引用

  3.[&]以引用的方式传入所有的变量

  4.[=]以传值的方式传入所有的变量,值不可以被修改

  5.[&,a]除了a用传值的方式,其他变量都已引用的方式传入

  6.[=,&a]除了a用引用的方式传入,其他变量都以传值的方式传入

  下面让我们通过一个例子来了解一下,当在lambda中使用了“=”传入的参数,且对引用参数或者外部参数进行赋值操作之后,会产生意想不到的结果,并且还需注意在使用“&”时需要注意引用对象的生命周期。

  

    /*Lambda表达式*/
int b, c, d;
auto func0 = [&]()->void {b = ; c = ; d = ; };
auto func1 = [=]()->int {return * ; };
auto func2 = [=, &b, &c]()->void {++b; c += d + b; };
auto func3 = [=]()->int {return b + d; }; func0(); //b,c,d分别为1,2,3
c=func1(); //c=6
func2(); //b=2;c=858993456,d=6;
b = func3();//b=1717986916
return ;

  当Lambda被定义在类的成员函数中时,Lambda可以调用该类的private函数;当Lambda调用该类的成员函数时,操作成员变量或者其他成员函数时,需要将this传入,=和&会传入this。

  使用std::function可以存储Lambda函数,比如可以用function<void()>来存储func0,用function<int()>来存储func1,带有参数的函数可以直接在()内输入参数类型,在使用function时要包含头文件functional。

  

    #include <functional>
function<void()> f1 = func0;
function<int()>f2 = func1;

  function还可以用于存放普通函数,静态函数和类的公有成员函数,前两者和lambda的用法一样,直接将函数名赋值给function对象即可(无法识别重载的函数),但类的成员函数需要使用bind来绑定:

  

    ClassA *obj = new ClassA();
function<void(int)> f2 = bind(&ClassA::memberFunc1,obj,std::placeholders::_1);
function<void(int, char)>f3 = bind(&ClassA::memberFunc2,obj,std::placeholders::_2);

  使用bind函数绑定成员函数和对象指针,使用std::placeholders占位符来表示函数的参数数量,其后缀依次从1~N。

6.显式虚函数重载

  override可以确保在重写父类的虚函数,调整父类的虚函数时(改名字或者参数),不会忘记调整子类的虚函数。在编译时,编译器会为标记为override的虚函数检查其父类是否有该虚函数:

class B{
public:
virtual void virtuaalFunc(int);
}; class C{
public:
virtual void virtuaalFunc(int) override; //显示重写父类虚函数
virtual void virtuaalFunc(char) override; //错误
};

  final可以保证子类不能重写函数,不能具有相同签名的函数,或者类不能被继承。(类似于Java中final用法)override和final并不是C++11的关键字,只是在特定的位置才有特殊的含义,在其他地方仍然是当作变量来用的。

作者:马三小伙儿
出处:http://www.cnblogs.com/msxh/p/5869992.html 
请尊重别人的劳动成果,让分享成为一种美德,欢迎转载。另外,文章在表述和代码方面如有不妥之处,欢迎

批评指正。留下你的脚印,欢迎评论!

【Cocos2d-x游戏开发】细数Cocos2d-x开发中那些常用的C++11知识的更多相关文章

  1. 细数Android开源项目中那些频繁使用的并发库中的类

    这篇blog旨在帮助大家 梳理一下前面分析的那些开源代码中喜欢使用的一些类,这对我们真正理解这些项目是有极大好处的,以后遇到类似问题 我们就可以自己模仿他们也写 出类似的代码. 1.ExecutorS ...

  2. 细数Javascript技术栈中的四种依赖注入

    作为面向对象编程中实现控制反转(Inversion of Control,下文称IoC)最常见的技术手段之一,依赖注入(Dependency Injection,下文称DI)可谓在OOP编程中大行其道 ...

  3. iOS cocos2d 2游戏开发实战(第3版)书评

    2013是游戏爆发的一年,手游用户也是飞速暴增.虽然自己不做游戏,但也是时刻了解手机应用开发的新动向.看到CSDN的"写书评得技术图书赢下载分"活动,就申请了一本<iOS c ...

  4. 细数Qt开发的各种坑(欢迎围观)

    1:Qt的版本多到你数都数不清,多到你开始怀疑人生.从4.6开始到5.8,从MSVC编译器到MINGW编译器,从32位到64位,从Windows到Linux到MAC.MSVC版本还必须安装对应的VS2 ...

  5. [模拟炉石](一)让游戏过程显示到cocos2d中

    在上篇中,如果运行了fireplace的tests/full_game.py,这个程序将一个游戏过程在终端上运行完成,可以看到整个过程,那么第一步要做的就是将这个过程显示到cocos2d创建的场景中去 ...

  6. 细数Python Flask微信公众号开发中遇到的那些坑

    最近两三个月的时间,断断续续边学边做完成了一个微信公众号页面的开发工作.这是一个快递系统,主要功能有用户管理.寄收件地址管理.用户下单,订单管理,订单查询及一些宣传页面等.本文主要细数下开发过程中遇到 ...

  7. Cocos2d—X游戏开发之CCToggle(菜单标签切换)CCControlSwitch(开关切换)

    Cocos2d—X游戏开发之CCToggle(菜单标签切换) 首先继承子CCMenu,是菜单标签中的一种.‘ class CC_DLL CCMenuItemToggle : public CCMenu ...

  8. cocos2D(一)----第一个cocos2D程序

    简单介绍 我们这个专题要学习的是一款iOS平台的2D游戏引擎cocos2d.严格来说叫做cocos2d-iphone,由于cocos2d有非常多个版本号.我们学习的是iphone版本号的.既然是个游戏 ...

  9. 细数 Windows Phone 灭亡的七宗罪(过程很详细,评论很精彩,但主要还是因为太慢了,生态跟不上,太贪了,厂商不愿意推广)

    曾梦想仗剑走天涯,看一看世界的繁华 年少的心有些轻狂,如今你四海为家 曾让你心疼的姑娘,如今已悄然无踪影 犹记得上大学攒钱买了第一台智能手机Lumia 520时,下载的第一首歌曲<曾经的你> ...

随机推荐

  1. 为何JAVA虚函数(虚方法)会造成父类可以"访问"子类的假象?

      首先,来看一个简单的JAVA类,Base. 1 public class Base { 2 String str = "Base string"; 3 protected vo ...

  2. SDL 截图、录像、录像播放

    截图 使用sdl很简单,视频显示窗口大小,不是视频分辨率大小 int i = Sdl.SDL_SaveBMP(surfacePtr, path); if(i != 0) { MessageBox.Sh ...

  3. centos apache svn配置

    单独安装svn服务: 安装svn软件 yum install subversion 创建根目录 mkdir -p /var/www/svn 创建版本库repos svnadmin create /va ...

  4. 4、JavaScript

    一.JavaScript的概念:是基于对象和事件的脚本语言. 1.特点: a).安全性. b).跨平台性(只要可以解释JS的浏览器就可以执行,和平台无关) 2.JavaScript与Java的区别: ...

  5. css浏览器兼容问题

    https://www.douban.com/group/topic/4629864/

  6. PHP中类的继承和构造函数的继承

    PHP4.x 版本: PHP 4.x 的构造函数名与类名相同. 子类的构造函数名与子类名相同(废话). 在子类里父类的构造函数不会自动执行. 要在子类里执行父类的构造函数,必须执行类似以下语句: $t ...

  7. C# 构建XML(简单示例)

    C# 构建XML的简单示例: var pars = new Dictionary<string, string> { {"url","https://www. ...

  8. 关于CDN的认识

    传统的未加缓存服务的访问过程: 用户提交域名→浏览器对域名进行解释→得到目的主机的IP地址→根据IP地址访问发出请求→得到请求数据并回复 由上可见,用户访问未使用CDN缓存网站的过程为: 1).用户向 ...

  9. JS中的call()和apply()方法

    1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call ...

  10. PYTHON 函数的动态参数

    #普通参数示例 def func(args): print(args) func(123456) #执行结果为123456 如果给多个参数,就会报错 #动态参数示例 def func(*args): ...