🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

1 total messages Started by Marshall Cline Tue, 21 Aug 1990 20:12
Disambiguating inherited pure virtuals with explicit qualifiers
#404
Author: Marshall Cline
Date: Tue, 21 Aug 1990 20:12
96 lines
5386 bytes
Suppose class A has a function f(), and class B also has a function f().
If C multiply inherits from A and B, then calling f() on a C is ambiguous.
Supposedly (ARM section 10.1.1) explicit qualification (ex: A::f) can be
used in C to disambiguate these f()'s.

But suppose A::f() is virtual and B::f() is pure virtual:
	class A { public: virtual int f();     };	//A concrete class
	class B { public: virtual int f() = 0; };	//An abstract class
	class C : public A, public B { public: A::f; };	//A concrete class???
(This is not as obscure as it looks -- see below for a real-life example!)

The rule for making a class non-abstract is that all pure virtuals need
to be `filled in.'  It seems reasonable that an explicit qualifier in C
such as `A::f' fully specifies the definition of C::f(), so C ought NOT
to be abstract.  Unfortunately this doesn't appear to be the case in
either g++ or Turbo-C++ (both seem to think that C is still abstract, as
well as giving a pre-2.1 complaint to either implement each pure virtual
or else re-declare them as pure virtual).

The only thing I've been able to do is fully implement C::f() as calling
B::f().  This gets old fast (especially when there are numerous member
functions to be re-implemented) since it also adds an extra (fortunately
non-virtual) function-call to each access.

Any light?  If this isn't already covered by the ARM (I didn't find it),
I propose that the following `reasonable' behavior be accepted as correct:

	When class C has multiple public base classes A and B, with A::f()
	being a (non-pure) virtual and B::f() being a pure virtual, an
	explict qualification in C such as `A::f;' means that f() is NOT
	a pure virtual in C.

Marshall Cline

PS: Here's the scenario that got me into this mess
(press 'n' if you're not interested...)

A common C++'ism (at least in my code!) is to hang several alternate
implementations of a `concept' from an abstract base class (ABC).  Ex:

                              Stack
                              (ABC)
                             /     \
                       VStack       LStack         etc etc
                  (Vector-based)   (List-based)

Now consider an `Invertable Stack' as a specialized Stack, and suppose
(rather than retrofitting an `invert()' member into each Stack class)
you want a separate hierarchy.  That's easy: create an InvStack ABC which
inherits from the Stack ABC.  There's no reason to prevent someone from
implementing VInvStack (the vector based InvStack) by inheriting from
VStack, which leads to multiple inheritance:

                   Stack
                   (ABC)
                     |  \________
                     |           \
                     |          InvStack
                     |           (ABC)
                   VStack          |
                        \______    |
                               \   |
                               VInvStack

I don't want to argue whether you *need* MI in this example -- clearly
VInvStack can *contain* a VStack (at the cost of reimplementing all the
member functions), or could *privately* derive from VStack (at the cost
of specifying the access of all VStack member functions as public).  I
just think the above is a natural and convenient strategy, since reusing
the VStack implementation means you only have to implement the
orthogonally added function `invert()'.

Furthermore note that `push()', `pop()', etc, will be pure virtual in
InvStack simply by reason of the fact that they were inherited as pure
virtual from Stack (this is a new rule in 2.1).  *However* VInvStack will
also inherit the *implemented* `push()', `pop()', etc, from VStack.

QUESTION: How can I convince the compiler to use VStack's implementation
of `push()'??

Neither GNU C++ nor Turbo-C++ accept explicit qualification (ex:
`VStack::push;') in the public section of VInvStack (when I try to
instantiate a VInvStack, both complain that I never gave an
implementation of a pure virtual).  The only thing I've been able to do
is re-implement each member function so it calls the VStack version.
This is unacceptable since it not only costs me implementation (and
maintenance) time, it also costs an extra (fortunately non-virtual)
function call for each access.
--
==============================================================================
Marshall Cline / Asst.Prof / ECE Dept / Clarkson Univ / Potsdam, NY 13676
cline@sun.soe.clarkson.edu / Bitnet:BH0W@CLUTX / uunet!clutx.clarkson.edu!bh0w
Voice: 315-268-3868 / Secretary: 315-268-6511 / FAX: 315-268-7600
Career search in progress; ECE faculty; research oriented; will send vita.
PS: If your company is interested in on-site C++/OOD training, drop me a line!
==============================================================================
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads