C++ 对象的成员函数反射

使用场景,假如你需要解析一个消息,里面有各种消息结构,例如你需要解析一个protobuf结构,
C++ 对象的成员函数反射_第1张图片
一般的写法,你需要判断每个字段是否存在,然后存在的话再做解析,如果这个消息字段很多的话,你可能要写一堆的if。
这边有个更好的方法,就是通过一个map存储解析这个pb结构的成员函数,实现成员函数的反射。

给个例子:

class Base {
public: 
    Base(std::string str1, std::string str2) : m_str1(str1), m_str2(str2) {
    }
    bool has1() {
        return false;
    }

    bool has2() {
        return true;
    }
    std::string & get1() {
        return m_str1;
    }
    std::string & get2() {
        return m_str2;
    } 

private:
    std::string m_str1;
    std::string m_str2;
    static const int d = 4;   
};

using RtbAdFeatureHasFuc = bool(Base::*)();
using RtbAdFeatureGetMeta = std::string&(Base::*)();

struct RtbAdFeatureFucSets
{
    RtbAdFeatureHasFuc hasFuc;
    RtbAdFeatureGetMeta getFuc;
};

std::map key2Choice = {
    {"not_target_media_struct", {&Base::has1, &Base::get1} },
    {"gender_struct", {&Base::has2, &Base::get2} }
};

int main()
{
    Base ba("b1","b2"); // 假如这个是 你需要解析的消息对象
    RtbAdFeatureHasFuc pf = &Base::has1;
  
    (ba.*pf)(); // pf 不是可以直接调用的对象,需要指定对象执行
    for (auto it = key2Choice.begin(); it != key2Choice.end(); ++it) {
        if ( (ba.*(it->second.hasFuc))() ) { // 必须添加(ba.*() ) 括号,优先级
            std::cout << (ba.*(it->second.getFuc))() << std::endl;
        } else {
            std::cout << "no : " << it->first;
        }
    }

    return 0;
}

上面最重要的的地方 在RtbAdFeatureGetMeta 这个声明你需要保持和你需要使用的成员函数类型一模一样,比如返回值类型,入参类型。

上面只是个简单的例子,当你的消息对象里面有很多的字段需要解析时,这个方法可以节省很多重复代码。

你可能感兴趣的:(C++ 对象的成员函数反射)