james@utastro.UUCP (James McCartney) (06/18/88)
I just saw a posting in comp.sys.mac.programmer for a 3 day talk on MPW C++ that included a discussion on multiple inheritance & virtual classes in C++. It also says that C++ has a very efficient run time implementation of mult- iple inheritance. I didn't think C++ had multiple inheritance. I've heard that there is a paper by Bjarne Stroustup on mult. inher. Could someone illuminate me on how mult. inher. can/could be done in C++. I know it can be worked around with friends and the like. What IS a virtual class and what is it for? --- James McCartney
mikem@otc.oz (Mike Mowbray) (06/21/88)
In article <2786@utastro.UUCP>, james@utastro.UUCP (James McCartney) says: > Could someone illuminate me on how mult. inher. can/could be done in C++. It can be done by an extension of the single inheritance mechanism. (Needs a new cfront of course.) The main problem is how to handle virtual member functions. E.g: class Male { public: virtual be_impotent(); // something specific to Males }; class Female { public: virtual have_period(); // something specific to Females }; class Hermaphrodite : public Male, public Female { public: be_impotent(); // Let's assume hermaphrodites have their // own form of impotency have_period(); // and that they have periods differently. }; Now consider: main() { Hermaphrodite h; Male *m = &h; Female *f = &h; m->be_impotent(); f->have_period(); } At the point where m->be_impotent() is called, cfront only knows that it's got a ptr to Male. But Hermaphrodite::be_impotent() expects a "this" which is a ptr to Hermaphrodite. In the single inheritance case, there is no difficulty, since the address of one is the address of the other. But in the multiple inheritance case there are different sub-objects like: struct _Hermaphrodite { // Male stuff struct _Female OFemale; }; The solution is to extend the vtbl's associated with each class to include offsets. I.e: instead of just being a table of pointers to functions, they're a table of pairs (pointer-to-fn, delta). So when a virtual member is invoked, you get something like: (*object->vptr[1].f)(((char*)&object) + object->vptr[1].delta , .....); > What IS a virtual class and what is it for? Ah. Virtual base classes are truly marvellous things. In ordinary MI, if a base class is a multiple grandparent, there are multiple sub-objects. E.g: class LinkItem { ... }; class A : public LinkItem { .... }; class B : public LinkItem { .... }; class Both : public A, public B {....}; Here class Both can simultaneously be on a list of A's and a list of B's, since its A and B sub-objects have separate LinkItem sub-objects. There are case, however, when one would like the grandparent sub-objects to be the same instance (i.e: shared or common). For example: class CommonData { protected: int i; } class A : virtual public Common { .... }; class B : virtual public Common { .... }; class Both : virtual public A, virtual public B { .... }; Here, if a member of A modifies CommonData::i, a member function of B will see the modification. (Unlike the non-virtual MI case above). This mechanism takes some skill to use reliably, especially within libraries, but is very nice. Think about it. Someone can write the A and B classes above, and someone else can write the "Both" class even if he only has object code for the CommonData, A and B classes. He thereby obtains an interaction between A and B through the common sub-object. Naturally the documentation of the behaviour of A and B needs to be very complete to do this confidently, and the original designer of A and B ought probably to have borne virtual base classes in mind. Even given these caveats, it's a very nice way to combine library classes when you don't have the source code. This would tend to imply that future library designers should always use virtual bases unless they have a very good reason not to. Mike Mowbray Systems Development |||| OTC || ACSnet: mikem@otc.oz TEL: (02) 287-4104 UUCP: {seismo,mcvax}!otc.oz!mikem SNAIL: GPO Box 7000, Sydney, Australia
cmc@inf.rl.ac.uk (Chris Crampton) (07/11/88)
In article <401@otc.oz> mikem@otc.oz (Mike Mowbray) writes: >... >This would tend to imply that future library designers should always use >virtual bases unless they have a very good reason not to. Indeed, if a library is to be truly extensible then it seems to me that the designers should make all methods and destructors virtual unless they have a good reason not to. Another tough decision for library designers is which methods (and possibly data) should be made protected instead of private. Bad decisions made early on can make things very difficult for programmers who are sub-classing rather than just using the existing classes. I sometimes wish that virtual were the default... Chris. ======================================================================= Chris M Crampton UK JANET: cmc@uk.ac.rl.inf Rutherford Appleton Labs, ARPA: cmc%inf.rl.ac.uk@nss.cs.ucl.ac.uk Didcot, OXON, U.K. UUCP: ..!mcvax!ukc!rlvd!cmc +44 235 21900 ext. 6756 cmc@rlvd.uucp