对象的成员定义为a.b
。有没有办法通过向量动态获取成员?例如:
struct foo{
std::string bar;
};
vector <foo> baz;
baz[0].bar = "0";
是否可以在声明baz.bar
时访问bar
? (实施例)
void a(std::string b) {
//not sure if this is how it works
std::cout << baz[0].{b};
}
答案 0 :(得分:3)
可以使用字符串访问对象成员的唯一方法是:
void doStuff(std::string_view m) {
if (m == "bar") {
// Do stuff with bar
} else if (/* other members */) {
// Stuff with other members
}
}
看起来很难看。这很难看。我不建议这样做。
C ++不支持使用字符串查找的原因是因为在运行时,没有关于代码本身的类型,名称和任何其他信息的信息。将这些数据添加到已编译的代码中只会导致内存膨胀和二进制膨胀,并且仅在选择的代码中有用。
有许多功能允许类似的语义,但是类型安全且比字符串更快。
C ++支持指向成员的指针。它们是一个可以等于类成员的变量。对于给定的实例,您可以动态访问该成员指向的内容。让我举个例子:
// This declares a pointer to member string data of the class foo
std::string foo::* someMember;
// Some member equals to the member bar
someMember = &foo::bar;
// We declare a foo
foo someFoo;
// Direct access to member
std::cout << someFoo.bar << std::endl;
// Access to the member via the pointer to member
std::cout << someFoo.*someMember << std::endl;
这样做的好处是你可以在运行时选择成员:
// Points to a string member of class foo
std::string foo::* someMember;
if ( someCondition ) {
someMember = &foo::bar;
} else {
// baz is another string member of foo
someMember = &foo::baz;
}
foo someFoo;
// Will either access bar or baz depending on the condition
std::cout << foo.*someMember << std::endl;
关于这一点的好处是这是类型安全的。指向成员的指针具有明确类别的确定类。这消除了字符串不等于你的类中的某些东西或类型错误的问题。
如果您不喜欢声明成员指针的语法,则可以始终使用auto:
// The type of auto is `std::string foo::*`
auto someMember = &foo::bar;
请注意someMember
的类型是在编译时推断出来的,并且在程序执行期间无法更改。
如果我要在有效的C ++中重写函数a
,它将如下所示:
template<typename MemberType>
void a(MemberType foo::* m) {
std::cout << baz[0].*m;
}
类型MemberType
将在编译时推断,就像auto
一样,因此您的函数可以与任何类型的成员一起使用。要了解有关模板的更多信息,请参阅您首选的C ++教程。
std::unordered_map
有时你真的需要按字符串查找东西。您希望在类中动态声明新成员并动态访问它们。在这种情况下,您需要的是一个地图数据结构:将某种类型的值映射到其他类型的另一个值的东西。
struct foo {
// We map some strings to some integers
std::unordered_map<std::string, int> values;
};
foo someFoo;
someFoo.values["bar"] = 12;
someFoo.values["baz"] = 15;
// Will print 12, then 15.
std::cout << someFoo.values["bar"] << std::endl;
std::cout << someFoo.values["baz"] << std::endl;
同样,类型安全在这里:您不能意外地将双重分配到地图中。查找类型将始终为字符串,并且关联的值将全部为整数。