Question

I'm working on code that contains several functions with the following pattern

memberType* var = NULL;
switch(someVariable)
{
  case 0: var = &object.MemberVariable1; break;
  case 1: var = &object.MemberVariable2; break;
  case 2: var = &object.MemberVariable3; break;
}

The member variables are of the same type. In some switches there are several dozen cases, which clutter up the function body with what's basically just data. I'd like to create an array, map or something similar so I could access the members based on the input value.

I'm thinking of having something like

sometype array[size] = {member1, member2, member3}

so the function could contain

memberType* var = array[index];

instead of the switch.

1. My first thought was creating a union in the class that contains the individual member variables and an array, so I can access either the individual members or access them via array + index. This is ugly, not apparent from the code at first glance and forces the member vars to be declared in a consecutive manner. It also does not allow me to access the same member variable for different indices.

2. Having an array that contains function pointers to functions that return individual member variables forces me to create tons of one line getter functions.

3. Having a statically allocated object so I can do something like

int offsets[size] = {
*(int*)&staticObject.member1 - *(int*)&staticObject,
*(int*)&staticObject.member2 - *(int*)&staticObject, 
*(int*)&staticObject.member3 - *(int*)&staticObject}

and use it

var = (memberType*)(*(int*)&object + offsets[index]);

is terrible.

Is there a nice way to get rid of this unnecessarily verbose pattern?

Disclaimer: I did not test the code used in the examples. It's just for illustration.


Edit: One important thing I forgot to mention: I don't want to change the size of the class because of serialization - I have yet to understand the implementation I'm working with.

Était-ce utile?

La solution

You may want to check out pointers to members. This will allow you to implement your suggestion (3) more cleanly.

Lets say your class looks like this.

class X {
public:
  memberType MemberVariable1;
  memberType MemberVariable2;
  memberType MemberVariable3;
};

Now we'll define an array of pointers to member variables.

typedef memberType X::*MemberVar;
MemberVar ptrs[3] = {
  &X::MemberVariable1,
  &X::MemberVariable2,
  &X::MemberVariable3
};

Then you can use the array like this.

X obj;
memberType var = obj.*(ptrs[index]);

Autres conseils

Just encapsulate the switch:

  1. In the object's class, define GetMemberVariableAt(int) and move the switch in there.
  2. Then, have your client code ask for object.GetMemberVariableAt(someVariable).

If you do this, it won't be all that important that you're using a nasty switch to get to the right member variable, because the switch will be internal to your object's implementation, not smeared across your code. And, you have the piece of mind that you can improve it later with minimal effort, switching to an array or whatever your mind (or your performance requirements, perhaps) desires.

If you don't control the source code of the class of your object, you can still proxy it or put an adapter in front of it, and code to the proxy or adapter.


The solution I am giving here is intended to make it easier to choose between the alternatives that you already offer in your question, by reducing the importance of the ugliness factor.

I should add that between the switch and an array of member references solution, I prefer the switch, because data duplication can be a wealthy source of latent bugs and complicated code. If you can replace the member variables with an array internally, I would go for that over the switch, but if you have to maintain both an array and the fields outside GetMemberVariableAt, this is data duplication that I would warmly recommend against.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top