[comp.lang.c++] Nonvirtual base classes in MI

sdm@cs.brown.edu (Scott Meyers) (01/26/91)

Look, I've used single inheritance, both public and private, and multiple
inheritance, with virtual base classes no less, but I've never yet come up
with a plausible reason for wanting nonvirtual base classes in an
application using MI in an inheritance DAG.  If you have an application
that uses nonvirtual base classes in an inheritance DAG, I'd appreciate it
if you'd drop me a line briefly describing what you do and why you need
duplicated base classes.

Thanks,

Scott


-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence?  "Hello, Mr. Mayor."

Reid Ellis <rae@gpu.utcs.toronto.edu> (01/30/91)

In <62555@brunix.UUCP> sdm@cs.brown.edu (Scott Meyers) writes:
>Look, if you have an application that uses nonvirtual base classes in
>an inheritance DAG, I'd appreciate it if you'd drop me a line briefly
>describing why you need duplicated base classes.

Because the compiler is broken and doesn't handle virtual base classes
properly? :-)

					Reid
--
Reid Ellis  176 Brookbanks Drive, Toronto ON, M3A 2T5 Canada
rae@gpu.utcs.toronto.edu      ||  rae%alias@csri.toronto.edu
CDA0610@applelink.apple.com   ||             +1 416 446 1644

mjv@objects.mv.com (Michael J. Vilot) (01/31/91)

Scott Meyers asked for an example of using multiple inheritance without using
virtual base classes.  I used exactly this approach in the design of the C++
Booch Components library, to use mixin classes to achieve a couple of purposes.

First, let me point out that the Booch Components library has a ``forest'' 
architecture, and thus avoids the common base class arrangement that leads to
the complexities of using MI in that context.  Second, I used private and 
public base classes for different design purposes.

The first use I made of MI was to create ``concrete'' classes from abstract
base classes (ABCs).  These concrete classes had both the ABC and a base class
for representation.  With this arrangement, the library can provide alternate 
implementations of the ABC, each with different time/space complexity.  In this
case, the base class for representation is a second, private base class.

The second use I made of MI was to mix in specific behavior for Node classes in
the unbounded representations.  Some of the Booch Components are what we call
``polylithic'' structures.  That is, they can share their representation among
several objects.  Shared_Nodes are kinds of Nodes that mix in a Shared base
class.  This approach let me build the Shared class once (implementing reference
counting), and mix it in as needed.  The library also supports Managed 
components, which take over free list management from the global operators new
and delete.  A Managed_Node mixes in a base class Managed, which provides the
class-specific operators new and delete.  Again, I only had to build that 
mechanism once to use it in various places.

I found the result to be quite satisfactory.  It clearly represents the design
structure, and helps keep the large library fairly well organized.  I think the
key to this is the separation between ``type'' and class that Doug Lea and
Marshall Cline described in their paper ``An Object Oriented Graphical Design
Method that Distinguishes Types from Classes'' that they presented at the GOOSE
workshop at ECOOPSLA last October.

--
Mike Vilot,  ObjectWare Inc, Nashua NH
mjv@objects.mv.com  (UUCP:  ...!decvax!zinn!objects!mjv)

linton@sgi.com (Mark Linton) (02/01/91)

In article <1159@zinn.MV.COM>, mjv@objects.mv.com (Michael J. Vilot) writes:
|> Scott Meyers asked for an example of using multiple inheritance without using
|> virtual base classes.  I used exactly this approach in the design of the C++
|> Booch Components library, to use mixin classes to achieve a couple of purposes.

 I think you missed the point of Scott's question.  You describe a situation
in which you did not need virtual base classes.  What Scott asked is if any one needs
non-virtual base classes.  Presumably, your code would have functioned correctly
if you had made all your derivations virtual (in fact, you really should make all your
reference counting derivations virtual because you don't want a descendant
to have multiple ref counts).

I would like to echo the original question, as I also have not encountered
a situation where I need non-virtual base classes.

sdm@cs.brown.edu (Scott Meyers) (02/01/91)

In reponse to my posting, Michael J. Vilot described his uses of nonvirtual
base classe with MI.  His examples were interesting, but I didn't see any
uses of a DAG.  Perhaps I wasn't explicit enough in what I was looking for.
What I want to see is an example that can be boiled down to this:

        A       class A { ... };
       / \
      /   \
     B     C    class B: public (or private) A { ... };
      \   /     class C: public (or private) A { ... };
       \ /
        D       class D: (optionally virtual) public (or private) B, 
                         (optionally virtual) public (or private) C { ... };

What's important here is that neither B nor C inherits from A as a virtual
base.  That results in the memory layout of a D object looking like this,
at least conceptually:

    +------------+
    | B's A Part |
    +------------+
    | B Part     |
    +------------+
    | C's A Part |
    +------------+
    | C Part     |
    +------------+
    | D Part     |
    +------------+

Notice that there are two A parts in a D object.

For the record, I fully agree with Michael's distinction between public and
private inheritance.  I'm especially interested in examples of the above
the use only public inheritance.

Scott

-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence?  "Hello, Mr. Mayor."

kgorlen@helix.nih.gov (Keith Gorlen) (02/02/91)

In article <1159@zinn.MV.COM>, mjv@objects.mv.com (Michael J. Vilot) writes:
|> Scott Meyers asked for an example of using multiple inheritance without using
|> virtual base classes.  I used exactly this approach in the design of the C++
|> Booch Components library, to use mixin classes to achieve a couple of purposes.
|> 
|> First, let me point out that the Booch Components library has a ``forest'' 
|> architecture, and thus avoids the common base class arrangement that leads to
|> the complexities of using MI in that context.  Second, I used private and 
|> public base classes for different design purposes.
|> 
|> The first use I made of MI was to create ``concrete'' classes from abstract
|> base classes (ABCs).  These concrete classes had both the ABC and a base class
|> for representation.  With this arrangement, the library can provide alternate 
|> implementations of the ABC, each with different time/space complexity.  In this
|> case, the base class for representation is a second, private base class.

It seems to me that there is little, if any, advantage to using private
inheritance as opposed to simply including an instance of the class as a member
variable, e.g.:

	class Concrete: public ABC, private Rep {
	// ...
	public:
		void foo();
	};

	void Concrete::foo() { Rep::f(); // ... }

versus:

	class Concrete: public ABC {
		Rep rep;
	// ...
	public:
		void foo();
	};

	void Concrete::foo()  { rep.f(); // ... }
		
Are there more compelling reasons for using private inheritance than this?

|> The second use I made of MI was to mix in specific behavior for Node classes in
|> the unbounded representations.  Some of the Booch Components are what we call
|> ``polylithic'' structures.  That is, they can share their representation among
|> several objects.  Shared_Nodes are kinds of Nodes that mix in a Shared base
|> class.  This approach let me build the Shared class once (implementing reference
|> counting), and mix it in as needed.  The library also supports Managed 
|> components, which take over free list management from the global operators new
|> and delete.  A Managed_Node mixes in a base class Managed, which provides the
|> class-specific operators new and delete.  Again, I only had to build that 
|> mechanism once to use it in various places.
|> 

Is this also a case of private inheritance?

|> --
|> Mike Vilot,  ObjectWare Inc, Nashua NH
|> mjv@objects.mv.com  (UUCP:  ...!decvax!zinn!objects!mjv)



-- 
	Keith Gorlen			phone: (301) 496-1111
	Building 12A, Room 2033		FAX: (301) 402-0007
	National Institutes of Health	uucp: uunet!kgorlen%alw.nih.gov
	Bethesda, MD 20892		Internet: kgorlen@alw.nih.gov

kgorlen@helix.nih.gov (Keith Gorlen) (02/02/91)

In article <63176@brunix.UUCP>, sdm@cs.brown.edu (Scott Meyers) writes:
|> In reponse to my posting, Michael J. Vilot described his uses of nonvirtual
|> base classe with MI.  His examples were interesting, but I didn't see any
|> uses of a DAG.  Perhaps I wasn't explicit enough in what I was looking for.
|> What I want to see is an example that can be boiled down to this:
|> 
|>         A       class A { ... };
|>        / \
|>       /   \
|>      B     C    class B: public (or private) A { ... };
|>       \   /     class C: public (or private) A { ... };
|>        \ /
|>         D       class D: (optionally virtual) public (or private) B, 
|>                          (optionally virtual) public (or private) C { ... };
|> 
|> What's important here is that neither B nor C inherits from A as a virtual
|> base.  That results in the memory layout of a D object looking like this,
|> at least conceptually:
|> 
|>     +------------+
|>     | B's A Part |
|>     +------------+
|>     | B Part     |
|>     +------------+
|>     | C's A Part |
|>     +------------+
|>     | C Part     |
|>     +------------+
|>     | D Part     |
|>     +------------+
|> 
|> Notice that there are two A parts in a D object.
|> 

Then I would draw the DAG like this:

	A     A
	|     |
	B     C
	 \   /
	   D	


Examples 13-1 and 13-2 in "Data Abstraction and Object-Oriented Programming
in C++" show multiply inheriting from class Link so that derived classes can
be threaded on multiple linked lists; i.e. class A = Link, class B = AllLink,
class C = QLink, and class D = Vehicle.

However, Tom Cargill's article in the most recent issue of "The C++ Journal"
shows how to do this example without using MI.

-- 
	Keith Gorlen			phone: (301) 496-1111
	Building 12A, Room 2033		FAX: (301) 402-0007
	National Institutes of Health	uucp: uunet!kgorlen%alw.nih.gov
	Bethesda, MD 20892		Internet: kgorlen@alw.nih.gov

bothner@sevenlayer.cs.wisc.edu (Per Bothner) (02/02/91)

In article <1991Jan31.164927.3234@odin.corp.sgi.com>, linton@sgi.com (Mark Linton) writes:
>I would like to echo the original question, as I also have not encountered
>a situation where I need non-virtual base classes.

Perhaps it should be emphasized that even if one doesn't
*need* non-virtual base classes, it may be reasonable
to use them anyway for efficiency reasons. The main example
is that of abstract base classes (or ones where the base
class is otherwise "constant.") If one has a class hierarchy
rooted in Object, it is undesirable to make Object a virtual
base class, since it would add an extra indirection to
*every virtual function call,* even for objects which
only actually inherit from Object along a single path.
-- 
	--Per Bothner
bothner@cs.wisc.edu Computer Sciences Dept, U. of Wisconsin-Madison

mjv@objects.mv.com (Michael J. Vilot) (02/08/91)

Keith Gorlen commented on my design decisions in the Booch Components library:
>It seems to me that there is little, if any, advantage to using private
>inheritance as opposed to simply including an instance of the class as a member
>variable,

I agree with Keith, and with Tom Cargill, that private base classes can be
transformed into class members.  There may be some minor performance
differences between the two, but I suspect on average it's a wash.  

> Are there more compelling reasons for using private inheritance than this?

Compelling?  Probably not -- certainly not, in any absolute sense.  Are there
_compelling_ reasons for deriving all classes from a root class Object?  Again,
probably not.  On the other hand, such decisions may make sense within a given
set of design goals and constraints. 

Each decision represents a particular design choice.  In my case, I used
private derivation to express the difference between the abstract class and the
``concrete'' classes derived from it -- the derived classes mix in their
representation.  Making the representation class a private base separates it
from the other members of the class, and highlights the design decision. 

|> The second use I made of MI was to mix in specific behavior for Node classes in
|> the unbounded representations.

>Is this also a case of private inheritance?

No, in this latter case the derivation has to be public:  Node classes mixing
in Managed behavior (similarly for Shared) make the added members publicly
available.  The simplicity of the Managed and Controlled forms hinges on the
transparent substitution of ``new'' and ``delete'' that occurs as a result.

I'm looking forward to a lively discussion in Washington !
--
Mike Vilot,  ObjectWare Inc, Nashua NH
mjv@objects.mv.com  (UUCP:  ...!decvax!zinn!objects!mjv)

sdm@cs.brown.edu (Scott Meyers) (02/08/91)

In article <1174@zinn.MV.COM> mjv@objects.mv.com (Michael J. Vilot) writes:
| I agree with Keith, and with Tom Cargill, that private base classes can be
| transformed into class members.  There may be some minor performance
| differences between the two, but I suspect on average it's a wash.  

No no no.  You lose virtual functions when you turn inheritance into member
containment.  There is a conceptual distinction between the following:

    A has a member B             ==> A "has a" B (or A "contains a" B)
    A publicly inherits from B   ==> A "is a" B
    A privately inherits from B  ==> A "is implemented in terms of a" B

Private inheritance is a convenient way to share code when there is no
other conceptual relationship between two classes.  I usually call this
"code stealing."  When stealing the code in another class, you often have
to do some class specific stuff; this is where virtual functions come in.
The member functions in the (private) base class can call virtual functions
to do the customization.  This won't work with member objects, because they
have no way of knowing what they're a part of.

| Each decision represents a particular design choice.  In my case, I used
| private derivation to express the difference between the abstract class and the
| ``concrete'' classes derived from it -- the derived classes mix in their
| representation.  Making the representation class a private base separates it
| from the other members of the class, and highlights the design decision. 

Right.  Each derived class object "is an" abstract class object, hence
public inheritance in that case.  However, each derived class object "is
implemented in terms of" an representation object, hence private inheritance.


Scott

-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence?  "Hello, Mr. Mayor."

kgorlen@alw.nih.gov (Keith Gorlen) (02/09/91)

In article <64173@brunix.UUCP>, sdm@cs.brown.edu (Scott Meyers) writes:
|> In article <1174@zinn.MV.COM> mjv@objects.mv.com (Michael J. Vilot) writes:
|> | I agree with Keith, and with Tom Cargill, that private base classes can be
|> | transformed into class members.  There may be some minor performance
|> | differences between the two, but I suspect on average it's a wash.  
|> 
|> No no no.  You lose virtual functions when you turn inheritance into member
|> containment.  There is a conceptual distinction between the following:
|> 
|>     A has a member B             ==> A "has a" B (or A "contains a" B)
|>     A publicly inherits from B   ==> A "is a" B
|>     A privately inherits from B  ==> A "is implemented in terms of a" B
|> 
|> Private inheritance is a convenient way to share code when there is no
|> other conceptual relationship between two classes.  I usually call this
|> "code stealing."  When stealing the code in another class, you often have
|> to do some class specific stuff; this is where virtual functions come in.
|> The member functions in the (private) base class can call virtual functions
|> to do the customization.  This won't work with member objects, because they
|> have no way of knowing what they're a part of.
|> 

That sounds like a good reason to me!

-- 
	Keith Gorlen			phone: (301) 496-1111
	Building 12A, Room 2033		FAX: (301) 402-0007
	National Institutes of Health	uucp: uunet!kgorlen%alw.nih.gov
	Bethesda, MD 20892		Internet: kgorlen@alw.nih.gov