我正在处理包含多个具有以下模式的函数的代码
memberType* var = NULL;
switch(someVariable)
{
case 0: var = &object.MemberVariable1; break;
case 1: var = &object.MemberVariable2; break;
case 2: var = &object.MemberVariable3; break;
}
成员变量属于同一类型。在一些开关中有几十个案例,它们使功能体与基本上只是数据相混淆。我想创建一个数组,地图或类似的东西,以便我可以根据输入值访问成员。
我想要有类似
的东西sometype array[size] = {member1, member2, member3}
所以函数可以包含
memberType* var = array[index];
而不是开关。
1 我的第一个想法是在类中创建一个包含单个成员变量和数组的联合,因此我可以访问各个成员或通过array + index访问它们。这是丑陋的,乍一看代码并不明显,并迫使成员变量以连续的方式声明。它也不允许我为不同的索引访问相同的成员变量。
2 有一个包含返回单个成员变量的函数的函数指针的数组迫使我创建大量的一行getter函数。
第3 有一个静态分配的对象,所以我可以做类似
的事情int offsets[size] = {
*(int*)&staticObject.member1 - *(int*)&staticObject,
*(int*)&staticObject.member2 - *(int*)&staticObject,
*(int*)&staticObject.member3 - *(int*)&staticObject}
并使用它
var = (memberType*)(*(int*)&object + offsets[index]);
太糟糕了。
有没有一种很好的方法可以摆脱这种不必要的冗长模式?
免责声明:我没有测试示例中使用的代码。这只是为了说明。
编辑:我忘了提到一件重要的事情:我不想因为序列化而改变类的大小 - 我还没有理解我正在使用的实现。< / p>
答案 0 :(得分:6)
您可能需要查看pointers to members。这将使您能够更清晰地实施您的建议(3)。
让我们说你的课看起来像这样。
class X {
public:
memberType MemberVariable1;
memberType MemberVariable2;
memberType MemberVariable3;
};
现在我们将定义一个指向成员变量的指针数组。
typedef memberType X::*MemberVar;
MemberVar ptrs[3] = {
&X::MemberVariable1,
&X::MemberVariable2,
&X::MemberVariable3
};
然后你可以像这样使用数组。
X obj;
memberType var = obj.*(ptrs[index]);
答案 1 :(得分:4)
switch
只需encapsulate:
GetMemberVariableAt(int)
并将开关移到那里。object.GetMemberVariableAt(someVariable)
。如果你这样做,那么你使用一个令人讨厌的开关来获得正确的成员变量并不是那么重要,因为这个开关将在你对象的实现内部,而不会污染你的代码。而且,你有一点心思,你可以稍后用最小的努力,改用阵列或任何你的想法(或者你的性能要求)来改进它。
如果您不控制对象类的源代码,您仍然可以代理它或在其前面放置一个适配器,并代码到代理或适配器。
我在此提供的解决方案旨在通过降低丑陋因素的重要性,让您更轻松地在问题中提供的替代方案中进行选择。
我应该在switch
和一组成员引用解决方案之间添加,我更喜欢switch
,因为数据重复可能是潜在错误和复杂代码的丰富来源。如果您可以在内部使用数组替换成员变量,我会在switch
上进行,但是如果您必须维护数组和GetMemberVariableAt
之外的字段,这是我热烈建议的数据重复。