3

我正在处理包含具有以下模式的多个函数的代码

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. 我的第一个想法是在包含单个成员变量和数组的类中创建一个联合,这样我可以访问单个成员或通过数组+索引访问它们。这很难看,乍一看从代码中并不明显,并强制成员 vars 以连续方式声明。它也不允许我访问不同索引的相同成员变量。

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]);

太可怕了。

有没有一种很好的方法来摆脱这种不必要的冗长模式?

免责声明:我没有测试示例中使用的代码。这只是为了说明。


编辑:我忘了提到一件重要的事情:我不想因为序列化而改变类的大小——我还没有理解我正在使用的实现。

4

2 回答 2

6

您可能想要检查指向成员的指针。这将使您能够更干净地实施您的建议 (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]);
于 2013-07-07T19:27:15.690 回答
4

只需封装switch:_

  1. 在对象的类中,定义GetMemberVariableAt(int)并在其中移动开关。
  2. 然后,让您的客户代码要求object.GetMemberVariableAt(someVariable).

如果您这样做,那么使用讨厌的开关来获取正确的成员变量就不是那么重要了,因为该开关将在您的对象实现内部,而不是在您的代码中涂抹。而且,您有一个想法,您可以在以后以最小的努力改进它,切换到阵列或您的想法(或您的性能要求,也许)想要的任何东西。

如果你不控制你的对象的类的源代码,你仍然可以代理它或在它前面放一个适配器,并编码到代理或适配器。


我在这里给出的解决方案旨在通过降低丑陋因素的重要性,让您更容易在您已经在问题中提供的替代方案之间进行选择。

我应该在switch成员引用解决方案和数组之间添加,我更喜欢switch,因为数据重复可能是潜在错误和复杂代码的丰富来源。如果您可以在内部用数组替换switch成员变量,我会在GetMemberVariableAt.

于 2013-07-07T18:53:50.167 回答