我遇到了一个设计问题,我希望你们可以提供帮助。我有一些具有各种参数的不同类(每种情况下超过20个,它们大多不同,尽管有些类完全相同,在这种情况下它们从基类继承)。我想通过名为ObjectProperties的类的用户来控制这些参数。每个类都将创建ObjectProperties,并在初始化类时使用它自己的参数列表填充它。这是通过如下设置的地图完成的:
std::map<std::string, [data_type]> // where [data_type] can be an int, float, bool, string etc.
'string'是参数的名称,数据类型是与之关联的类型。这样做是为了以后轻松编写脚本(而不是有20多个getter / setter)。我已经创建了ObjectProperties类,但它并不理想。我有一个结构,其中包含所有可能的数据类型,称为DataTypeStruct,以及一个名为pDataTypeMap的ObjectProperties类中的映射变量;
typedef struct
{
int* IntValue;
float* FloatValue;
bool* BoolValue;
std::string* StringValue;
}DataTypeStruct;
std::map<std::string, DataTypeStruct> pDataTypeMap;
当一个类想要为操作添加一个参数时,它会调用以下函数之一,然后适当地创建一个新结构并将其与要放入映射中的名称配对。该函数返回true或false,具体取决于它是否能够插入(如果为false,则名称已存在)
bool AddParam(std::string aName, int* aParam);
bool AddParam(std::string aName, float* aParam);
bool AddParam(std::string aName, bool* aParam);
bool AddParam(std::string aName, std::string* aString);
aParam 是指针的原因是因为必须通过引用传递参数,以便以后可以对它们进行操作。
要更改参数的值,我有类似的功能。正如你所看到的,这不太理想,因为我浪费了一些结构空间(每个新结构只存储一个int或一个bool或一个字符串或一个浮点数),调用重载函数是不安全的(我可以'使函数具有唯一的名称,但同样,这不是理想的。)
我希望我已经解释了我遇到的设计问题(这有点难以解释)并且非常希望听到关于如何解决这个问题的建议。
答案 0 :(得分:4)
我建议您首先查看boost::any,boost:variant,boost::tuple或boost::fusion::vector作为[data_type]的“车辆”。
答案 1 :(得分:2)
看起来你正在尝试重新发明boost::any。
答案 2 :(得分:1)
看起来很容易只有4个地图而不是1个有4组数据。然后,您的AddParam()方法将根据重载选择正确的映射,并为您的Get。
选择相同的映射您必须担心它们存储具有相同名称但不同类型的多个项目。您可以遍历所有4个映射,也可以使用整个对象中的项目名称保留一个单独的Set。
答案 3 :(得分:0)
要减少内存使用量,请使用union而不是DataTypeStruct
的结构。您的代码中的任何其他内容都不必更改(访问成员与结构相同)。现在,您的结构只需要与其中最大元素一样多的内存(可能为填充/对齐提供或占用几个字节)。
您还可以在函数中使用通用指针,并根据需要将其强制转换为适当的类型。例如:
enum data_type {INT, FLOAT, BOOL, STRING};
bool AddParam(std::string aName, void* pData, enum data_type type);
现在你有一个功能来处理所有类型。使用type
的值来确定如何在函数内重新转换指针。
答案 4 :(得分:0)
此处的建议是将DataTypeStruct
更改为
typedef struct
{
void* value;
int type;
//e.g.
//0 for empty,1 for int*,2 for float*,
//3 for bool*,4 for string* etc.
}DataTypeStruct;
然后,您可以拥有一个AddParam
功能
bool AddParam(std::string aName, void* aParam, int type);
您将该功能称为
int a;
float b;
bool c;
std::string d;
AddParam("test1", (void*)a, 1);
AddParam("test2", (void*)b, 2);
AddParam("test3", (void*)c, 3);
AddParam("test4", (void*)d, 4);
要获得该值,您可以使用如下函数
void* GetParam(std::string aName);
通过调用
使用它int a_return = *((int*)GetParam("test1"));
float b_return = *((float*)GetParam("test2"));
bool c_return = *((bool*)GetParam("test3"));
std::string d_return = *((std::string*)GetParam("test3"));
现在一切看起来都很干净,可以为新类型扩展,并且可以节省浪费的空间:)
快乐的节目!