cocos2dx源码阅读之万能的Value

cocos2dx源码阅读之万能的Value,第1张

概述近日在学习cocos2dx引擎的使用时,阅读了某些常用的类的源码。在此进行总结。 1.概述 版本:cocos2d-x-3.12 语言:C++ 在cocos2dx-3.x之前,存在着一些原生类型的封装类,如 CCBool, CCFloat, CCDouble, CCinteger等,来完成对原生数据类型的封装,但在3.0版本出现之后,这些都被一个名叫Value的类替代了。 cocos2d::Val

近日在学习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,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与其封装类型之间的相互转换。其代码实现并不难,但此设计思想实在是秒,尤其是将值使用共用体来表示,在完成需要的同时还节省了空间。

总结

以上是内存溢出为你收集整理的cocos2dx源码阅读之万能的Value全部内容,希望文章能够帮你解决cocos2dx源码阅读之万能的Value所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1080868.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存