如果我有一个类如:
class Car {
string name;
int age;
string manufacturer;
}
我显示一个汽车列表,其中包含名称,年龄,制造商的过滤器下拉列表。如何比较汽车各自的属性?
我可以使用switch语句,但如果有很多字段,这将无法管理。
在JS或Objective-C(使用KVC)中,您可以动态访问对象的属性,因此这很容易。
具体来说,我问的是C ++中用于访问在编译时无法知道的变量或成员函数的等效模式是什么,因为它是由用户在运行时提供的。
答案 0 :(得分:2)
您通常会使用std::map<>
来存储属性,而不是单个数据成员。
这具有允许在运行时创建属性的附加优势,因此整个数据模型可以是动态的和数据驱动的。
答案 1 :(得分:1)
语言中没有内置的等效模式:与JS,Objective-C和其他具有重量级元数据的语言不同,C ++只能为您的代码提供有限的运行时信息,完成后也没有任何帮助。你的任务。
但是,这并不意味着无法构建自己的元数据。您可以创建一个函数,将字符串值与对象的字段进行比较,将这些函数的映射到相应的字段,然后使用映射中的函数按名称访问字段(如同):
// Field equality comparers
map<string,function<bool(Car&,string&)>> carFieldEq = {
{"name", [] (Car &c, string& cmp) { return c.name == cmp; }}
, {"age", [] (Car &c, string& cmp) { return to_string(c.age) == cmp; }}
, {"manufacturer", [] (Car &c, string& cmp) { return c.manufacturer == cmp; }}
};
// Field less-than comparers
map<string,function<bool(Car&,string&)>> carFieldLess = {
{"name", [] (Car &c, string& cmp) { return c.name < cmp; }}
, {"age", [] (Car &c, string& cmp) { return c.age < std::stoi(cmp); }}
, {"manufacturer", [] (Car &c, string& cmp) { return c.manufacturer < cmp; }}
};
您可以按如下方式使用这些地图:
auto cars = vector<Car> {
{"Impala", 10, "Chevrolet"}
, {"Focus", 3, "Ford"}
, {"Jetta", 3, "VW"}
};
string fieldNameEq, eqCmp;
cin >> fieldNameEq >> eqCmp;
cout << "==== Cars matching " << fieldNameEq << "==" << eqCmp << ":" << endl;
for (auto &c : cars) {
if (carFieldEq[fieldNameEq](c, eqCmp)) {
cout << c.name << " " << c.age << " " << c.manufacturer << endl;
}
}
string fieldNameLess, lessCmp;
cin >> fieldNameLess >> lessCmp;
cout << "==== Cars matching " << fieldNameLess << "<" << lessCmp << ":" << endl;
for (auto &c : cars) {
if (carFieldLess[fieldNameLess](c, lessCmp)) {
cout << c.name << " " << c.age << " " << c.manufacturer << endl;
}
}
请注意,carFieldEq
和carFieldLess
采用任意字符串,该字符串可能不一定与字段的实际名称相匹配。