[comp.lang.c++] MI and library extension

vaughan@puma.cad.mcc.com (Paul Vaughan) (09/21/89)

	This is partly a followup to Craig Zarmer's excellent
description of the problem of extending libraries.  The problem arises
when many library classes inherit non-virtually from a library base
class, and one wants to create new versions of these derived classes
based on an extended version of that base class, without modifying the
library source.  For instance, in the example below, I might want to
have a list of objects that derive from both LibBase and MyBase (some
of which might be MyDerived objects), where the list pointer type
allows me to call both foo() from LibBase and bar() from MyBase.
Remember that there is a problem if I derive MyDerived from the
Bogus class and from LibDerived.  MyDerived would get two LibBase
components.  This can't be helped because LibDerived derives from
LibBase non-virtually and that code cannot be changed.
	I want to know what the informed experts (and opinionated
non-experts like me) think of this usage of C++ multiple inheritance.
I particularly want to know if the cast is going to work or cause
trouble.  This example compiles and runs with g++ 1.35.1.

#include <stream.h>

//-----------------------  fixed library code : Hands Off
class LibBase {
public:
  LibBase() { cout << "LibBase Constructor\n";};
  foo() { cout << "LibBase::foo()\n";};
};

class LibDerived : public LibBase {     // one of many
public:
  LibDerived() { cout << "LibDerived Constructor\n";};
};

//------------------------  my extension code : rearrange at will
class MyBase {
public:
  MyBase() { cout << "MyBase Constructor\n";};
  bar() { cout << "MyBase::bar()\n";};
};

// one for every interesting LibDerived class
class MyDerived :  public MyBase, public LibDerived {  
public:
  MyDerived() { cout << "MyDerived Constructor\n"; };
};


// Bougs is used only to represent things that inherit from both
// MyBase and LibBase.
// No Bogus objects are ever made and nothing derives from Bogus

class Bogus : public MyBase, public LibBase {};
//-------------------------

main() { 

// Although MyDerived (or other similar classes it represents)
// does not derive from Bogus, I know that MyDerived inherits from the
// same base classes as Bogus.  I may assume that it inherits from no
// other base classes, but I'm not sure if that is necessary for this
// cast to work.

  Bogus* bogus = (Bogus*) new MyDerived;
  bogus->foo();
  bogus->bar();
}


[1.229]puma) lib2
MyBase Constructor
LibBase Constructor
LibDerived Constructor
MyDerived Constructor
LibBase::foo()
MyBase::bar()

Give it a rating:

  Incredibly useful (donations accepted), 
  Interesting technique,
  So who cares, but it's guaranteed to work in all implementations,
	given the assumptions,
  Dubious at best,
  An accident waiting to happen,
  Author deserves a Pox and revocation of programmer's license

Also, I'd be obliged if people would people try it in their
implementation, regardless of their theoretical answer.

 Paul Vaughan, MCC CAD Program | ARPA: vaughan@mcc.com | Phone: [512] 338-3639
 Box 200195, Austin, TX 78720  | UUCP: ...!cs.utexas.edu!milano!cadillac!vaughan