使用场景,假如你需要解析一个消息,里面有各种消息结构,例如你需要解析一个protobuf结构,
一般的写法,你需要判断每个字段是否存在,然后存在的话再做解析,如果这个消息字段很多的话,你可能要写一堆的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<std::string, RtbAdFeatureFucSets> 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 这个声明你需要保持和你需要使用的成员函数类型一模一样,比如返回值类型,入参类型。
上面只是个简单的例子,当你的消息对象里面有很多的字段需要解析时,这个方法可以节省很多重复代码。