Path: utzoo!telly!attcan!uunet!image.soe.clarkson.edu!news From: cline@cheetah.ece.clarkson.edu (Marshall Cline) Newsgroups: comp.std.c++ Subject: Disambiguating inherited pure virtuals with explicit qualifiers Message-ID: Date: 21 Aug 90 20:12:28 GMT Sender: news@sun.soe.clarkson.edu Reply-To: cline@sun.soe.clarkson.edu (Marshall Cline) Distribution: comp Organization: (I don't speak for the) ECE Dept, Clarkson Univ, Potsdam, NY Lines: 97 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! ==============================================================================