不
C++ 没有自省和反射能力。您必须自己编写这种动态访问的代码。
在某些情况下,手动编码的合理替代方案可以使用外部模式文件来描述您的 C++ 类,然后自动生成类以及内省和反射代码。你不能使用模板来做到这一点,因为在这个领域甚至完全没有 C++ 的元编程能力。
由于 C++ 语法的复杂性,通过直接解析生成代码.h
通常要困难得多(即使是编译器制造商也花了好几年的时间才在相当程度上同意什么是有效的 C++ 代码,什么不是)。
您可以使用模板来简化发布,但仍需手动操作:
template<typename T, typename C>
std::map<std::string, T C::*>& attribute_map() {
static std::map<std::string, T C::*> m;
return m;
}
template<typename C>
struct Published {
template<typename T>
T& attribute(const std::string& name) {
std::map<std::string, T C::*>& m = attribute_map<T, C>();
typename std::map<std::string, T C::*>::const_iterator i=m.find(name);
if (i == m.end()) {
throw std::runtime_error("Attribute not present");
} else {
return static_cast<C *>(this)->*i->second;
}
}
};
对于每个属性,您需要明确“发布”它
template<typename T, typename C>
void publish(const std::string& name, T C::*mp) {
attribute_map<T, C>()[name] = mp;
}
鉴于上述样板代码,您可以创建一个类并通过派生以下方式发布其一些成员Published<Class>
:
struct MyClass : Published<MyClass> {
int a;
double b;
std::string c;
MyClass(int a, double b, const std::string& c)
: a(a), b(b), c(c)
{
}
};
然后,您将需要publish
在程序开始时只调用一次该函数,以便能够动态访问属性:
int main(int argc, const char *argv[]) {
publish("a", &MyClass::a);
publish("b", &MyClass::b);
publish("c", &MyClass::c);
MyClass m1(3, 4.5, "This is a test");
MyClass m2(6, 7.8, "This is another test");
std::cout << m1.attribute<int>("a") << "\n";
std::cout << m2.attribute<std::string>("c") << "\n";
return 0;
}