Xref: utzoo comp.lang.c++:14142 comp.std.c++:959 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!think.com!rpi!uupsi!sunic!sics.se!fuug!fuug!pena From: pena@brainware.fi (Olli-Matti Penttinen) Newsgroups: comp.lang.c++,comp.std.c++ Subject: Re: Adding multiple inheritance to a single inheritance class library. Message-ID: Date: 17 Jun 91 08:10:41 GMT References: <10971@castle.ed.ac.uk> <1991Jun14.113736.3795@jyu.fi> Sender: usenet@fuug.fi (USENET News System) Organization: Brainware Oy, Espoo, Finland. Lines: 91 In-Reply-To: sakkinen@jyu.fi's message of Fri, 14 Jun 1991 11: 37:36 GMT Nntp-Posting-Host: brainw.brainware.fi In article <1991Jun14.113736.3795@jyu.fi> sakkinen@jyu.fi (Markku Sakkinen) writes: In article <10971@castle.ed.ac.uk> gaa@castle.ed.ac.uk (Gerard A. Allan) writes: > >Many C++ libraries have a common root class and as a consequence they >contain many functions and methods that take the root class as an >argument requiring a cast to the desired type inside the function. >This can cause a problem when attempting to use multiple inheritance and >a virtual base class. [ ex. deleted ] >This is of course perfectly true (ARM 10.6c) "Casting form a virtual >base class to a derived class is disallowed to avoid requiring an >implementation to maintain pointers to enclosing objects". This >makes it very difficult to use multiple inheritance and virtual bases >from a library with a single root class. Have you realised how utterly dangerous your 'Derived::function' is in the first place? From one viewpoint it is a blessing that virtual base classes prevent such casts, which can cause any amount of havoc. There is no assurance that actual arguments will in fact refer to Derived objects, unless 'function' is redefined in no other class in your whole programme. Yes, libraries like NIH, which *VERY* much depend on up-casting are indeed troublesome when combined with multiple inheritance (MI). They always enforce the user to follow some additional protocol to make the classes work with the rest of the world. To circumvent (sp?) the problem, there are very few alternatives with current C++ implementations. The best approach I've found is to view non-virtual derivation as inclusion of the base object (with added complexity due to virtual functions, of course) and virtual derivation as indirectly including (referring to) a common instance of a base class object. TODO: the client code should use its natural type hierarchies to define the appropriate classes, but instead of deriving from (say NIH) existing classes with the aforementioned behavior a pointer to such an object should be defined as a private member. Another problem arises: who should construct the subobject? The best answer is found in ARM 12.6.2: the most derived class is responsible. At times it is somewhat difficult to ensure at compile time that any given class is indeed a leaf class. An additional boolean member could be included to indicate whether the (conseptually) virtual base object has been initialized. Also, watch out for assignment! Most (all, I think) current implementations incorrectly assign virtual base objects multiple times (once per occurence). Sometimes it only degrades performance, at other times can be disastrous. More object-oriented languages than C++ (Simula, Eiffel, ...) typically enforce run-time checking of such casts to make them safe; in C++ such checking is not even possible. It was a deliberate (and in my opinion unfortunate) desing decision in C++ that all objects do not carry sufficient type information like they do in those others languages. There has been (and still is) discussion on the subject. On the one hand, run time type information would be desirable, not only for typesafe runtime polymorhism but for high level debugging purposes, as well. On the other hand, any additional hidden overheads definitely are not in "the spirit of C", which C++ tries to honor. >Is there some way round this problem so that I can combine classes in a >"natural" way ? After all, the cast is not ambiguous since there is only >one Derived. What solutions to this problem have C++ programmers >developed or is multiple inheritance incompatible with the single >inheritance methodology ? And finally, is there a case for requiring >"an implementation to maintain pointers to enclosing objects" ? With type information in each object, there would be no need for the restriction. Eiffel seems to have no sweat with situations like this. In C++ there is hardly any other solution than to hand-code an additional level of object-orientation and be sure to use it in all appropriate classes. I suppose some of the large general-purpose C++ class libraries have been built that way. A better way to solve the problem altogether would be templates. With them, the libraries could be got right in the first place. Code size would of course increase because of numerous duplications, but that shouldn't be such a problem with current virtual memory techniques. At least that would clearly be the method of choice from a large scale software engineering viewpoint, whatever that may be :-) ==pena -- Olli-Matti Penttinen | "When in doubt, use brute force." Brainware Oy | --Ken Thompson P.O.Box 330 +---------------------------------- 02151 ESPOO, Finland Tel. +358 0 4354 2565 Fax. +358 0 461 617