more inheritance patterns

Discussion in 'C++' started by Mick Charles Beaver, Jun 27, 2008.

  1. Hello,

    At work, someone showed me a way to avoid virtual functions while
    maintaining an interface class.

    Basically,

    class _MyClass {
    void Method;
    };

    #if defined(LINUX)
    #include "linux/MyLinuxClass.h"
    class MyClass : public MyLinuxClass {};

    #elif defined(WINDOWS)
    #include "windows/MyWindowsClass.h"
    class MyClass : public MyWindowsClass {};
    #endif

    Then, throughout the code base, MyClass would be used, following the
    interface defined in _MyClass, while still allowing platform-specific
    code where needed.

    My question is, where could I read about more constructions like this?
    My coworker called it an "inheritance pattern." I'd love to learn more
    about them (even though I'm sure a case can be made for avoiding this
    style).

    Thanks much,
    Mick Charles Beaver
     
    Mick Charles Beaver, Jun 27, 2008
    #1
    1. Advertising

  2. Mick Charles Beaver

    James Kanze Guest

    On Jun 27, 5:39 am, (Mick Charles Beaver) wrote:
    > At work, someone showed me a way to avoid virtual functions
    > while maintaining an interface class.


    > Basically,


    > class _MyClass {
    > void Method;


    > };


    > #if defined(LINUX)
    > #include "linux/MyLinuxClass.h"
    > class MyClass : public MyLinuxClass {};


    > #elif defined(WINDOWS)
    > #include "windows/MyWindowsClass.h"
    > class MyClass : public MyWindowsClass {};
    > #endif


    > Then, throughout the code base, MyClass would be used,
    > following the interface defined in _MyClass, while still
    > allowing platform-specific code where needed.


    > My question is, where could I read about more constructions
    > like this? My coworker called it an "inheritance pattern."
    > I'd love to learn more about them (even though I'm sure a case
    > can be made for avoiding this style).


    It looks unwieldy and awkward to me. Anytime you need to use
    #if's, there's something wrong. The usual solution in such
    cases is to define MyClass using the compliation firewall idiom
    (so that none of the data members are in the header), and
    compile against it. Then provide separate implementations for
    each of the platforms, and link against whichever one is
    appropriate. Alternatively, the class is an abstract base
    class, with all of the functions pure virtual, and a static
    function to construct instances; again, you link against the
    appropriate library, which contains the definition for the
    correct derived class. (In the case of windowing under X,
    you'll often defer the linking until runtime, and choose a
    dynamically linked object according to some environment variable
    or a command line switch, in order to allow the user to choose
    whichever look and feel he wants.)

    I've called this link time polymorphism once or twice. I
    don't know if it has any real generally accepted name, but it's
    very wide spread.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 27, 2008
    #2
    1. Advertising

  3. Alf P. Steinbach <> wrote:
    > 1. Name that starts with underscore followed by uppercase, "_MyClass",
    > is reserved for the implementation.


    I agree that should change.

    > 2. Non-virtual member functions can't be overridden.


    This is a programmer enforced design, which requires never using a
    pointer to the "abstract" base class. It's a high-performance
    requirement, where virtual functions have too high of an overhead and
    must be avoided. It's the compile-time version of using a pure-virtual
    base class.

    > 3. Direct includes of platform-specific definitions pollutes namespaces
    > with platform-specific things.


    That is certainly the case, and purposefully so. Other parts of the code
    base can then #ifdef small sections out where calls to the derived
    platform-specific class can be made.

    Thanks for your response,
    Mick Charles Beaver
     
    Mick Charles Beaver, Jun 27, 2008
    #3
  4. Mick Charles Beaver

    Noah Roberts Guest

    Mick Charles Beaver wrote:
    > Hello,
    >
    > At work, someone showed me a way to avoid virtual functions while
    > maintaining an interface class.
    >
    > Basically,
    >
    > class _MyClass {
    > void Method;
    > };
    >
    > #if defined(LINUX)
    > #include "linux/MyLinuxClass.h"
    > class MyClass : public MyLinuxClass {};
    >
    > #elif defined(WINDOWS)
    > #include "windows/MyWindowsClass.h"
    > class MyClass : public MyWindowsClass {};
    > #endif
    >
    > Then, throughout the code base, MyClass would be used, following the
    > interface defined in _MyClass, while still allowing platform-specific
    > code where needed.
    >


    I don't understand, are you saying that you cast your MyClass objects to
    _MyClass? I don't see how you could otherwise be getting any behavior
    from your MyClass objects at all. The subclassing thing I understand
    but I don't see what _MyClass is doing.

    Frankly, the simplest way to implement non-virtual polymorphism is with
    templates. Whatever this is that you're doing looks like some odd,
    non-enforceable hack that might even exhibit undefined behavior.

    Furthermore, one should always consider if virtual functions are really,
    in fact, an issue before trying to "solve" the virtual polymorphism problem.

    But like I said, I obviously don't fully understand what you're doing.
    Can you clarify, provide a complete example possibly?
     
    Noah Roberts, Jun 27, 2008
    #4
  5. Alf P. Steinbach <> wrote:
    >> This is a programmer enforced design, which requires never using a
    >> pointer to the "abstract" base class. It's a high-performance
    >> requirement, where virtual functions have too high of an overhead and
    >> must be avoided.

    >
    > Have you measured, and if so, what were the results?


    I don't have any hard numbers at my disposal, but on the particular
    architecture where it is an issue, virtual functions almost always
    result in a branch misprediction.

    > #ifdef-based code is a point number 4.
    >
    > It seems you folks go out of your way to create an unmaintainable mess. :-(
    >
    > If was weened off #ifdef-based code in 1985 or thereabouts. You don't need it.
    > It's stupid.


    I believe it has its place. Maintainability is always a goal, so this
    construct and its associated #ifdef's are used sparingly.

    -Mick
     
    Mick Charles Beaver, Jun 27, 2008
    #5
  6. Mick Charles Beaver

    James Kanze Guest

    On Jun 27, 7:06 pm, (Mick Charles Beaver) wrote:
    > Alf P. Steinbach <> wrote:


    > >> This is a programmer enforced design, which requires never using a
    > >> pointer to the "abstract" base class. It's a high-performance
    > >> requirement, where virtual functions have too high of an overhead and
    > >> must be avoided.


    > > Have you measured, and if so, what were the results?


    > I don't have any hard numbers at my disposal, but on the particular
    > architecture where it is an issue, virtual functions almost always
    > result in a branch misprediction.


    Sounds like HP PA. Still what you're hiding here is system
    dependencies, i.e. system calls. Even a branch misprediction is
    negligible compared to the context switch to system mode, and
    everything which goes on there.

    > > #ifdef-based code is a point number 4.


    > > It seems you folks go out of your way to create an
    > > unmaintainable mess. :-(


    > > If was weened off #ifdef-based code in 1985 or thereabouts.
    > > You don't need it. It's stupid.


    > I believe it has its place.


    I has its place, yes. Obfuscation and job security, for
    example. Other than that, any #if other than an include guard
    is really serious enough to get a programmer fired, at least if
    I'm in charge.

    > Maintainability is always a goal, so this construct and its
    > associated #ifdef's are used sparingly.


    Actually, as you presented it, the construct doesn't need the
    #if's at all. You just have to organize your code a little
    better. (But of course, as you presented it, the construct just
    added a lot of code for nothing anyway.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 27, 2008
    #6
  7. Mick Charles Beaver

    James Kanze Guest

    On Jun 27, 6:17 pm, Noah Roberts <> wrote:
    > Mick Charles Beaver wrote:
    > > At work, someone showed me a way to avoid virtual functions
    > > while maintaining an interface class.


    > > Basically,


    > > class _MyClass {
    > > void Method;
    > > };


    > > #if defined(LINUX)
    > > #include "linux/MyLinuxClass.h"
    > > class MyClass : public MyLinuxClass {};


    > > #elif defined(WINDOWS)
    > > #include "windows/MyWindowsClass.h"
    > > class MyClass : public MyWindowsClass {};
    > > #endif


    > > Then, throughout the code base, MyClass would be used,
    > > following the interface defined in _MyClass, while still
    > > allowing platform-specific code where needed.


    > I don't understand, are you saying that you cast your MyClass
    > objects to _MyClass? I don't see how you could otherwise be
    > getting any behavior from your MyClass objects at all. The
    > subclassing thing I understand but I don't see what _MyClass
    > is doing.


    > Frankly, the simplest way to implement non-virtual
    > polymorphism is with templates.


    Even that's unnecessary additional complexity (and not a very
    good solution for this particular problem). In this case, link
    time resolution handles all of the problems simply and
    elegantly.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 27, 2008
    #7
  8. > Even that's unnecessary additional complexity (and not a very
    > good solution for this particular problem). In this case, link
    > time resolution handles all of the problems simply and
    > elegantly.


    Would you be able to recommend any web resources for learning more about
    link time resolution?

    Thank you
     
    Mick Charles Beaver, Jun 27, 2008
    #8
  9. Mick Charles Beaver

    Noah Roberts Guest

    Mick Charles Beaver wrote:
    >> Even that's unnecessary additional complexity (and not a very
    >> good solution for this particular problem). In this case, link
    >> time resolution handles all of the problems simply and
    >> elegantly.

    >
    > Would you be able to recommend any web resources for learning more about
    > link time resolution?
    >
    > Thank you


    I never said what you are quoting above. Who did? Did you reply to the
    posting you intended to?
     
    Noah Roberts, Jun 27, 2008
    #9
  10. Mick Charles Beaver

    Noah Roberts Guest

    Alf P. Steinbach wrote:
    > * Mick Charles Beaver:
    >> Alf P. Steinbach <> wrote:
    >>> 1. Name that starts with underscore followed by uppercase, "_MyClass",
    >>> is reserved for the implementation.

    >>
    >> I agree that should change.
    >>
    >>> 2. Non-virtual member functions can't be overridden.

    >>
    >> This is a programmer enforced design, which requires never using a
    >> pointer to the "abstract" base class. It's a high-performance
    >> requirement, where virtual functions have too high of an overhead and
    >> must be avoided.

    >
    > Have you measured, and if so, what were the results?
    >
    > It's interesting if you have done so, because to the best knowledge
    > available virtual functions have near to zero overhead.


    Well, they certainly won't be inlined.
     
    Noah Roberts, Jun 27, 2008
    #10
  11. Noah Roberts <> wrote:
    > I never said what you are quoting above. Who did? Did you reply to the
    > posting you intended to?


    Yet another good reason to attribute a quote to someone.

    Ugh.

    -Mick
     
    Mick Charles Beaver, Jun 27, 2008
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. crichmon
    Replies:
    4
    Views:
    503
    Mabden
    Jul 7, 2004
  2. Michael
    Replies:
    4
    Views:
    451
    Matt Hammond
    Jun 26, 2006
  3. abcd
    Replies:
    4
    Views:
    465
    Gabriel Genellina
    Jan 8, 2007
  4. Replies:
    18
    Views:
    1,653
    Odalrick
    Nov 18, 2007
  5. Robert Klemme

    With a Ruby Yell: more, more more!

    Robert Klemme, Sep 28, 2005, in forum: Ruby
    Replies:
    5
    Views:
    229
    Jeff Wood
    Sep 29, 2005
Loading...

Share This Page