cocos2dx源码阅读之万能的Value
来源:互联网 发布:org.apache jar包 编辑:程序博客网 时间:2024/06/04 22:22
近日在学习cocos2dx引擎的使用时,阅读了某些常用的类的源码。在此进行总结。
1.概述
版本:cocos2d-x-3.12 语言:C++
在cocos2dx-3.x之前,存在着一些原生类型的封装类,如 CCBool, CCFloat, CCDouble, CCinteger等,来完成对原生数据类型的封装,但在3.0版本出现之后,这些都被一个名叫Value的类替代了。
cocos2d::Value是一个模板容器类,完成了对很多数据类型的封装。如原生类型int, float, char, char*, bool,以及string,map,vector等stl模板类。
Value极大的方便了cocos2dx工程里各种数据类型之间的转换。我们可以很同意的将不同数据类型转换为Value,反之亦然。
2.源码
#include <CCValue.h>文件位置cocos2d-x-XXX/cocos/base/CCValue.h
2.1 成员变量
class CC_DLL Value{public: //一个预定义的空值,暂时还不知道其作用 static const Value Null; //枚举类,封装所有的数据类型名 enum class Type { /// no value is wrapped, an empty Value NONE = 0, /// wrap byte BYTE, /// wrap integer INTEGER, /// wrap unsigned UNSIGNED, /// wrap float FLOAT, /// wrap double DOUBLE, /// wrap bool BOOLEAN, /// wrap string STRING, /// wrap vector VECTOR, /// wrap ValueMap MAP, /// wrap ValueMapIntKey INT_KEY_MAP };private: //用共用体封装多种数据类型 保存Value的值,极大的节省了空间 union { unsigned char byteVal; int intVal; unsigned int unsignedVal; float floatVal; double doubleVal; bool boolVal; std::string* strVal; ValueVector* vectorVal; ValueMap* mapVal; ValueMapIntKey* intKeyMapVal; }_field; //记录当前Value内保存的数据类型 Type _type;}
总结:Value用一个枚举类保存数据的类型,用一个共用体保存数据的值(极大的节省了空间),用这两项完成对多种数据的保存。
2.2 成员函数
class CC_DLL Value{public: /*************************************** 对多种类型均设置了构造函数,并用explicit设置其不可隐式转换,实现基本类型到Value类型的转换 ****************************************/ //构造函数 Value(); explicit Value(unsigned char v); explicit Value(int v); explicit Value(unsigned int v); explicit Value(float v); explicit Value(double v); explicit Value(bool v); explicit Value(const char* v); explicit Value(const std::string& v); explicit Value(const ValueVector& v); explicit Value(ValueVector&& v); explicit Value(const ValueMap& v); explicit Value(ValueMap&& v); explicit Value(const ValueMapIntKey& v); explicit Value(ValueMapIntKey&& v); //拷贝构造函数 Value(const Value& other); //移动构造函数 Value(Value&& other); //析构函数 ~Value(); /*************************************** 重载各种数据类型的=,!=, ==运算符,实现基本类型与Value类型的操作 ****************************************/ Value& operator= (const Value& other); Value& operator= (Value&& other); Value& operator= (unsigned char v); Value& operator= (int v); Value& operator= (unsigned int v); Value& operator= (float v); Value& operator= (double v); Value& operator= (bool v); Value& operator= (const char* v); Value& operator= (const std::string& v); Value& operator= (const ValueVector& v); Value& operator= (ValueVector&& v); Value& operator= (const ValueMap& v); Value& operator= (ValueMap&& v); Value& operator= (const ValueMapIntKey& v); Value& operator= (ValueMapIntKey&& v); bool operator!= (const Value& v); bool operator!= (const Value& v) const; bool operator== (const Value& v); bool operator== (const Value& v) const; /*************************************** 上面的构造函数,以及运算符重载都实现的是基本类型到Value类型的转换,那么下面众多asXXX函数实现了Value类型到基本类型的转换,两者结合才是真正实现了两者的互相转换 ****************************************/ unsigned char asByte() const; int asInt() const; unsigned int asUnsignedInt() const; float asFloat() const; double asDouble() const; bool asBool() const; std::string asString() const; ValueVector& asValueVector(); const ValueVector& asValueVector() const; ValueMap& asValueMap(); const ValueMap& asValueMap() const; ValueMapIntKey& asIntKeyMap(); const ValueMapIntKey& asIntKeyMap() const; //判断Value是否为空 //若类型为空则Value亦为空 inline bool isNull() const { return _type == Type::NONE; } //获取Value类型 inline Type getType() const { return _type; } //获取类的描述,作用于string,vector,map等类型 std::string getDescription() const;private: //用于释放Value内变量的空间,会在析构函数里调用 void clear(); //重置Value并设置类型 void reset(Type type);};
2.3 详细分析
2.3.1构造函数
以int,string为例,其他的都大同小异
//很直观,直接进行了 类型_type和值_field两个成员变量的初始化Value::Value(int v): _type(Type::INTEGER){ _field.intVal = v;}//相较于基本类型,多了一步开辟空间Value::Value(const std::string& v): _type(Type::STRING){ _field.strVal = new (std::nothrow) std::string(); *_field.strVal = v;}
2.3.2 析构函数
Value::~Value(){ clear();}//析构函数仅调用了clear,下面说说clear函数void Value::clear(){ // Free memory the old value allocated switch (_type) { //如果是基本类型,则直接对其值进行重置即可 case Type::BYTE: _field.byteVal = 0; break; case Type::INTEGER: _field.intVal = 0; break; //........省略部分内容 /******************* 如果是string等需要释放空间的对象,调用CC_SAFE_DELETE宏来进行处理。 #define CC_SAFE_DELETE(p) do { delete (p); (p) = nullptr; } while(0) 该宏的功能很简单,释放指针指向的空间,并将指针置为空 *******************/ case Type::STRING: CC_SAFE_DELETE(_field.strVal); break; case Type::VECTOR: CC_SAFE_DELETE(_field.vectorVal); break; //........省略部分内容 default: break; } //将type重置 _type = Type::NONE;}
2.3.3 Value转化函数asXXX
同样,这里仅以asInt()为例
int Value::asInt() const{ //断言宏,如果条件表达式不符合,则中断程序并输出调试语句 CCASSERT(_type != Type::VECTOR && _type != Type::MAP && _type != Type::INT_KEY_MAP, "Only base type (bool, string, float, double, int) could be converted"); //本身就是Int,直接返回 if (_type == Type::INTEGER) { return _field.intVal; } //根据不同的类型进行转换操作 if (_type == Type::UNSIGNED) { CCASSERT(_field.unsignedVal < INT_MAX, "Can only convert values < INT_MAX"); return (int)_field.unsignedVal; } if (_type == Type::BYTE) { return _field.byteVal; } if (_type == Type::STRING) { return atoi(_field.strVal->c_str()); } if (_type == Type::FLOAT) { return static_cast<int>(_field.floatVal); } if (_type == Type::DOUBLE) { return static_cast<int>(_field.doubleVal); } if (_type == Type::BOOLEAN) { return _field.boolVal ? 1 : 0; } //若进行到这一步,则表明type不是以上类型,则认为它不能与int进行转换,直接返回0 return 0;}
2.3.4 reset重置函数
//函数功能为将value重置为其他类型void Value::reset(Type type){ //如果类型相同,则操作完成 if (_type == type) return; //否则,先清除之前空间,然后根据不同类型对_field进行初始化 clear(); // Allocate memory for the new value switch (type) { case Type::STRING: _field.strVal = new (std::nothrow) std::string(); break; case Type::VECTOR: _field.vectorVal = new (std::nothrow) ValueVector(); break; case Type::MAP: _field.mapVal = new (std::nothrow) ValueMap(); break; case Type::INT_KEY_MAP: _field.intKeyMapVal = new (std::nothrow) ValueMapIntKey(); break; default: break; } //更改_type,重置操作完成 _type = type;}
3.总结
看了源码,没有想象中的痛苦,反而带着一种享受,感慨人家的代码怎么可以写的那么好,那么条理清楚。
总结一下:Value类通过将所有数据类型都分化为 值 和类型 两部分,然后一系列操作都围绕着两部分,来实现Value与其封装类型之间的相互转换。其代码实现并不难,但此设计思想实在是秒,尤其是将值使用共用体来表示,在完成需要的同时还节省了空间。
0 0
- cocos2dx源码阅读之万能的Value
- Cocos2dx源码阅读 启动流程
- Cocos2dx源码分析之JumpBy的实现
- cocos2dx中Android.mk的万能模板
- cocos2dx之商店源码
- cocos2dx源码之 选择器
- android 源码阅读之C++的引用
- JDK源码阅读之HashMap的实现
- freeDiameter源码阅读之 Extensions 的实现
- 源码阅读之ArrayList
- 源码阅读之Vector
- cocos2dx源码之 CREATE_FUNC宏
- cocos2dx 源码分析之 CCPoolManager
- 万能的webView之Activity
- Android万能适配器CommonAdapter的源码分析
- cocos2dx 3.x 源码阅读之一 引用计数原理
- 阅读源码的方法
- mockpp的源码阅读
- hdu3980Paint Chain+SG博弈
- 机房收费系统总结
- MVP的工作原理
- Java设计模式-单例模式
- 找点题做(hdu分类)
- cocos2dx源码阅读之万能的Value
- SQL四中连接(左外连接、右外连接、内连接、全连接)
- hdu 1006
- 手机震动
- java中的缓存
- hdu 5501(贪心+01背包)
- 函数覆盖及其使用举例
- Shapefile的局限性
- Codeforces Round #343 (Div. 2) B. Far Relative’s Problem (贪心)