Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 与操作未知类型相关的设计问题_C++_Design Patterns - Fatal编程技术网

C++ 与操作未知类型相关的设计问题

C++ 与操作未知类型相关的设计问题,c++,design-patterns,C++,Design Patterns,我遇到了一个设计问题,希望你们能帮我解决。我有几个不同的类,它们有不同的参数(每种情况下都有20多个参数,它们大部分是不同的,尽管有些完全相同,在这种情况下它们从基类继承)。我想通过名为ObjectProperties的类的用户来控制这些参数。初始化类时,每个类将创建ObjectProperties并使用自己的参数列表填充它。这是通过如下设置的地图完成的: std::map<std::string, [data_type]> // where [data_type] can be a

我遇到了一个设计问题,希望你们能帮我解决。我有几个不同的类,它们有不同的参数(每种情况下都有20多个参数,它们大部分是不同的,尽管有些完全相同,在这种情况下它们从基类继承)。我想通过名为ObjectProperties的类的用户来控制这些参数。初始化类时,每个类将创建ObjectProperties并使用自己的参数列表填充它。这是通过如下设置的地图完成的:

std::map<std::string, [data_type]> // where [data_type] can be an int, float, bool, string etc.
aParam之所以是/are指针,是因为必须通过引用传递参数,以便以后可以对其进行操作

要更改参数的值,我有类似的函数。如您所见,这不太理想,因为我在结构上浪费了一些空间(每个新结构只存储int、bool、string或float),调用重载函数是不安全的(我“可以”使函数具有唯一的名称,但这也不理想)


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

要减少内存使用,请对
DataTypeStruct
使用联合而不是结构。代码中的任何其他内容都不需要更改(访问成员与访问结构相同)。现在,您的结构只需要与其中最大的元素一样多的内存(可能需要几个字节来填充/对齐)

您还可以在函数中使用泛型指针,并根据需要将其转换为适当的类型。例如:

enum data_type {INT, FLOAT, BOOL, STRING};
bool AddParam(std::string aName, void* pData, enum data_type type);

现在您有了一个处理所有类型的函数。使用
type
的值来确定如何在函数内重新转换指针。

似乎很容易只使用4个映射,而不是1个包含4组数据。然后,AddParam()方法将基于重载选择正确的映射,GET也是如此


您必须担心它们存储多个名称相同但类型不同的项目。您可以遍历所有4个映射,或者在整个对象中保留一个单独的项名称集。

这里的建议是将
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"));
现在一切看起来都很干净,可扩展为新类型,节省了浪费的空间:)


快乐编程

>我建议先看一看,或者作为你的[ DATAAYTYPE ]的“车辆”。

看起来你是在试图改造。

你应该真正考虑Boo::变型,你会喜欢这个设计。它似乎是为你的问题而设计的。如果可能的话,我更喜欢
变体
而不是
任何
任何
都不值得麻烦。谢谢,这就是我要找的。我没有太多使用boost,也不知道boost:variant/any甚至存在!这是我当前的实现,不幸的是,它的问题是我必须搜索所有四个映射(或更多,当添加更多类型时),以从给定的键中找到正确的值,除非我创建了四个GetParam函数(我确实创建了),例如GetParamInt,GetParamFloat等。太多膨胀了,在以后准备脚本时不是很好。我曾想过使用void*并将其用于类中的某些功能,但因为它不安全,并且很难捕获运行时错误,所以我想避免它。事实上,我当前实现中的AddParam函数调用函数:bool AddParam(std::string aName,void*aParam,DataType aDataType);其中DataType是支持的数据类型的枚举。这方面的主要问题是GetParam,在这种情况下,我必须使用void*,我想避免这种情况,因为它很容易出错。@Samaursa-该并集是指针的并集;它应该能够保存一个
std::string*
。我刚才看到了这个回复,你说得绝对正确。我用你的建议解决了另一个类似的问题。
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"));