如何优雅的写C++代码 Obotcha介绍(简单的反射实现一)

    最近又准备蠢蠢欲动开始写Sql的ORM了。但是ORM遇到的第一个问题就是C++没有反射!!!!。用过Java的同学都知道,使用Java的反射就能实现简单的ORM功能。奈何C++没有,只能自己实现一下了。主要实现代码如下:

    https://github.com/wangsun1983/Obotcha/blob/master/lang/include/Reflect.hpp

    代码中主要的宏定义就是:DECLARE_REFLECT_FIELD

#define DECLARE_REFLECT_FIELD(CLASS, ...) \
    std::map<std::string,std::function<void(std::string) >> mSetMaps;\
    IMPLE_SET_FUNCTION_DETECT(_##CLASS,GET_ARG_COUNT(__VA_ARGS__),__VA_ARGS__) \
    void __ReflectInit() {\
        IMPLE_INIT_FUNCTION_DETECT(_##CLASS,GET_ARG_COUNT(__VA_ARGS__),__VA_ARGS__)\
    }\
    void setFieldValue(String field,String value) {\
        mSetMaps[field->getStdString()](value->getStdString());\
    }\
  • 使用方法:在类声明中加入类似这样的宏定义DECLARE_REFLECT_FIELD(类名,变量名1,变量名2,....)示例代码如下:
    #define DECLARE_REFLECT_FIELD(CLASS, ...) \
        std::map<std::string,std::function<void(std::string) >> mSetMaps;\
        IMPLE_SET_FUNCTION_DETECT(_##CLASS,GET_ARG_COUNT(__VA_ARGS__),__VA_ARGS__) \
        void __ReflectInit() {\
            IMPLE_INIT_FUNCTION_DETECT(_##CLASS,GET_ARG_COUNT(__VA_ARGS__),__VA_ARGS__)\
        }\
        void setFieldValue(String field,String value) {\
            mSetMaps[field->getStdString()](value->getStdString());\
        }\
    

     

  • mSetMaps用来存放变量名字和变量设定函数的键值对,其中设定函数暂时统一使用:std::function<void(std::string)>。实际上的变量设定函数是通过一个宏去实现的,可以看到这个函数实际上就是void(std::string):
    #define IMPLE_SET_VALUE_1(CLASS,MEMBER) \
        void __ReflectSet##MEMBER(std::string v) { \
            std::stringstream iss(v);\
            iss>>this->MEMBER;\
        }

     

  • IMPLE_SET_FUNCTION_DETECT会遍历DECLARE_REFLECT_FIELD中传入了所有变量,逐个生成每个变量的设定函数。
  • __ReflectInit这个函数会在Object创建的时候被调用一次,自动把IMPLE_SET_FUNCTION_DETECT生成的设定函数和变量名存入mSetMaps。这个是Obotcha中创建实例的create函数实现,为了反射,我们在实例创建后多加入了__ReflectInit的调用。

    #define MAKE_FUNCTION_0(Y) \
    template<typename... Args>\
    sp<_##Y> create##Y(Args&&... args)\
    {\
        Object* obj = new _##Y(std::forward<Args>(args)...);\
        obj->__ReflectInit();\
        sp<_##Y> ret;\
        ret.set_pointer(dynamic_cast<_##Y *>(obj));\
        return ret;\
    }\

     

  • setFieldValue就是类似Java反射的设定函数。

完成这些修改后,我们就可以愉快的使用反射了。先来看一下简单的json反射成class实例的代码:


DECLARE_SIMPLE_CLASS(MyReflectData) {
public:
    int a;
    double d;
    DECLARE_REFLECT_FIELD(MyReflectData,a,d)
};

int testreflect() {
    JsonReader mReader = createJsonReader(createFile("reflect.json"));
    MyReflectData data = mReader->reflect<st(MyReflectData)>();
    std::cout<<"a is "<<data->a<<";d is "<<data->d;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值