Search code examples
c++attributesvirtualgetter

C++ Virtual Methods for Class-Specific Attributes or External Structure


I have a set of classes which are all derived from a common base class. I want to use these classes polymorphically. The interface defines a set of getter methods whose return values are constant across a given derived class, but vary from one derived class to another. e.g.:

enum AVal
{
  A_VAL_ONE,
  A_VAL_TWO,
  A_VAL_THREE
};

enum BVal
{
  B_VAL_ONE,
  B_VAL_TWO,
  B_VAL_THREE
};

class Base
{
  //...
  virtual AVal getAVal() const = 0;
  virtual BVal getBVal() const = 0;
  //...
};

class One : public Base
{
  //...
  AVal getAVal() const { return A_VAL_ONE };
  BVal getBVal() const { return B_VAL_ONE };
  //...
};

class Two : public Base
{
  //...
  AVal getAVal() const { return A_VAL_TWO };
  BVal getBVal() const { return B_VAL_TWO };
  //...
};

etc.

Is this a common way of doing things? If performance is an important consideration, would I be better off pulling the attributes out into an external structure, e.g.:

struct Vals
{
  AVal a_val;
  VBal b_val;
};

storing a Vals* in each instance, and rewriting Base as follows?

class Base
{
  //...
  public:
    AVal getAVal() const { return _vals->a_val; };
    BVal getBVal() const { return _vals->b_val; };
  //...
  private:
    Vals* _vals;
};

Is the extra dereference essentially the same as the vtable lookup? What is the established idiom for this type of situation? Are both of these solutions dumb? Any insights are greatly appreciated


Solution

  • The first method seems clearer and forces you to override those methods (at the first child anyway). I think the overhead of virtual calls tends to be less than one might expect. Only if you profile the code and the virtual calls are taking a ton of time would I attempt to do optimizations as in your second approach.

    That being said, what problem are you trying to solve? Sometimes class ids like this are useful but sometimes a different interface abstraction can accomplish the same thing without having have such an interface at all.