假设我的班级有一个整数数据成员:
class MyClass {
public:
MyClass();
private:
int my_int;
}
现在构建时,我希望收到一个数据类型,名称和值,所有都被编码为字符串:
public MyClass(string type, string name, string value) { ... }
根据类型和名称,在构造时将该值分配给我的数据成员。类似于:
public MyClass(string type, string name, string value)
{
this->parse(type, name, value);
}
private parse(string type_, string name_, string value_)
{
if (type_=="int")
{
int* int_ = getDataMember(name_);
(*int_)=atoi(value_);
}
else ....
}
所以现在当我声明MyClass c("int","my_int","5")
时,c将被初始化,其my_int
数据成员的值设置为5.
问题是我不知道如何实现getDataMember(字符串名称)。但它显然会返回一个指向名称“name”的数据成员的指针。
答案 0 :(得分:3)
虽然这不是C ++应该如何使用,但它并非完全不可能。
#include <string>
#include <map>
class MyClass {
public:
MyClass(const std::string& type, const std::string& name, const std::string& value);
private:
void parse(const std::string& type_, const std::string& name_, const std::string& value_);
template <typename T>
T* getDataMember(const std::string& name);
int my_int;
double my_double;
char my_char;
std::map<std::string, char*> members; //Map of strings to member memory locations
};
MyClass::MyClass(const std::string& type, const std::string& name, const std::string& value)
{
//List of members will have to be hardcoded
members["my_int"] = reinterpret_cast<char*>(&my_int);
members["my_double"] = reinterpret_cast<char*>(&my_double);
members["my_char"] = reinterpret_cast<char*>(&my_char);
this->parse(type, name, value);
}
template <typename T>
T* MyClass::getDataMember(const std::string& name) {
return reinterpret_cast<T*>(members[name]); //Will need to handle invalid names
}
void MyClass::parse(const std::string& type_, const std::string& name_, const std::string& value_)
{
if (type_=="int")
{
int* int_ = getDataMember<int>(name_);
(*int_)=atoi(value_.c_str());
}
}
int main(void) {
MyClass c("int","my_int","5");
return 0;
}
我们的想法是保持map
引用string
成员地址。使用string
访问地图将返回与string
对应的成员的地址。但是,当将新成员引入该类时,必须对此map
进行硬编码。此外,getDataMember
函数必须处理将无效名称传递给类的情况。
<强>低效率强>
string
比较从根本上来说很慢。比较发生了
当你将成员插入map
时,当你要去的时候
通过您的parse
函数尝试识别类型,以及何时
你在地图上搜索正确的密钥。
摆脱硬编码的可能方法
假设有一种方法可以在没有硬编码的情况下填充地图。这将涉及了解班级中存在哪些数据成员。由于C ++中似乎没有这样的功能,我们必须解析文件,或者至少解析包含该类的文件部分。但是,我们需要在编译文件之前完成此操作。这给我们留下了两个选择:
<强>结论强>
我认为最好找到你想要解决的问题的另一种方法,或者使用另一种语言,因为似乎C ++不是为此而构建的。
考虑您的真正问题
我相信您正在寻找的解决方案称为反序列化。
class MyClass {
public:
void Deserialize(XMLParser xml);
private:
int my_int;
double my_double;
char my_char;
};
void MyClass::Deserialize(XMLParser xml) {
while(xml.ReadLine() != "MEMBERS"); //Advances the XML parser to the line that specifies the members
//Proceed to deserialize the members in order
//This requires the file to list the members in the correct order
my_int = atoi(xml.ReadLine().c_str());
my_double = atof(xml.ReadLine().c_str());
my_char = atoi(xml.ReadLine().c_str());
}