与操纵未知类型有关的设计问题

时间:2010-07-13 17:57:38

标签: c++ design-patterns

我遇到了一个设计问题,我希望你们可以提供帮助。我有一些具有各种参数的不同类(每种情况下超过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或一个字符串或一个浮点数),调用重载函数是不安全的(我可以'使函数具有唯一的名称,但同样,这不是理想的。)

我希望我已经解释了我遇到的设计问题(这有点难以解释)并且非常希望听到关于如何解决这个问题的建议。

5 个答案:

答案 0 :(得分:4)

我建议您首先查看boost::anyboost:variantboost::tupleboost::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"));

现在一切看起来都很干净,可以为新类型扩展,并且可以节省浪费的空间:)

快乐的节目!