more inheritance patterns

  • Thread starter Mick Charles Beaver
  • Start date
M

Mick Charles Beaver

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
 
J

James Kanze

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

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.
 
M

Mick Charles Beaver

Alf P. Steinbach said:
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
 
N

Noah Roberts

Mick said:
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?
 
M

Mick Charles Beaver

Alf P. Steinbach said:
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
 
J

James Kanze

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.
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.)
 
J

James Kanze

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.
 
M

Mick Charles Beaver

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
 
N

Noah Roberts

Mick said:
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?
 
N

Noah Roberts

Alf said:
* Mick Charles Beaver:

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.
 
M

Mick Charles Beaver

Noah Roberts said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top