[LC++]Big objects in a class interface: good techniques?

Dr Mark H Phillips mark at austrics.com.au
Mon Mar 31 12:21:02 UTC 2003


It seems to be good practice, when designing a class
interface, to implement attributes through public functions
which refer to private storage.  Eg we do:

  struct Light {
    int intensity() const {return intensityVt;}
    ...
  private:
    int intensityVt;
    ...
  };

rather than doing:

  struct Light {
    int intensity;
    ...
  };

This way if we want to change how we implement the "intensity"
attribute, we may do so without affecting the interface.

But what if our attribute is a large object?  Eg:

  struct Light {
    ...
    Wiring wiring() const {return wiringVt;}
    ...
  private:
    ...
    Wiring wiringVt;
    ...
  };

where "wiring" is a large object type giving complex details on
exactly how the light is wired.  With this implementation, every
time you want to access some information about how the light is
wired the whole "wiringVt" object is copied!  This is obviously
very inefficient.

I could go:

   ...
   Wiring const& wiring() const {return wiringVt;}
   ...

but then this has memory management problems.  It is giving out the
address of an internal object.  What if this address becomes invalid?
The interface is no longer a safe one.

Alternatively I could bring the Wiring interface "to the surface" of
the Light interface:

  struct Light {
    ...
    int wiringEarth() const {return wiringVt.earth();}
    int wiringRed() const {return wiringVt.red();}
    int wiringGreen() const {return wiringVt.green();}
    std::string wiringPanel() const {return wiringVt.panel();}
    ...
  };

which sometimes might be the right solution, but sometimes is not.
It is a lot of extra effort for little return.  It means that if
the Wiring type gets modified, then so does the Light one.  It
means the interface is "flat" when you may want it hierachical.  You
are relying on naming conventions (ie prefacing each of these
attributes with "wiring") to show the structure of the object,
rather than representing the structure using built-in structure.  And
once you start getting several levels deep in hierachy it gets even
more messy.

So what is the solution?!  It seems we either get inefficient but safe;
or efficient but unsafe; or safe and efficient but very messy, inelegant
and hard to maintain.

Surely there is a better option?

Thanks in advance,

Mark.

P.S. With the solution:

   ...
   Wiring const& wiring() const {return wiringVt;}
   ...

will the inlining of the compiler get rid of the extra pointer
reference here?  Ie, will it compile it as effectively:

  ...
  Wiring const wiringVt;
  ...

?

-- 




More information about the tuxCPProgramming mailing list