Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!zephyr.ens.tek.com!tekcrl!brucec From: brucec@phoebus.phoebus.labs.tek.com (Bruce Cohen;;50-662;LP=A;) Newsgroups: comp.lang.c++ Subject: efficient virtual functions in leaf functions (a technique) Message-ID: Date: 14 Sep 90 01:47:43 GMT Sender: news@tekcrl.LABS.TEK.COM Organization: Tektronix Inc. Lines: 141 Here's a way for a class library developer to supply the class user with leaf class member functions which can respond virtually when called in the context of a base class object or object pointer, and inline when called in the context of a leaf class object or object pointer. It also allows the user to derive from the leaf class and restore the virtuality of the functions in the derived class. I really don't think this is a big deal, but enough people have talked about wanting to do something along these lines that I thought it would be worth sharing. And I can't help but think that someone else must have thought of this before. // test of concept for inlining virtual functions in leaf classes, while // allowing the leaf to be subclassed and the virtuality of the function // restored. // // The basic notion is to declare a public interface function (non-virtual, // prefereably inline) in the base class, which calls a protected virtual // function which does all the work. Derived classes (other than leaves) // simply redefine the virtual to do what is necessary. Leaf classes // overload the interface function with an inline which does the actual // work, then redefine the virtual function to call the interface function, // so that the right thing will happen on a virtual call. // // If you want a derived class of the leaf which allows virtuality again, // it just needs to overload the interface function to call the virtual, // and put the working code back in the virtual. One drawback: you will not // be able to use the original leaf class as the root of the new // inheritance graph for purposes of calling that virtual, but that is no // big loss. // // This is a relatively brainless example which is small enough to actually // look at the Cfront generated c code. The code looks OK, and the output // of the program is what you would expect: // // I'm a virtual Root // I'm a virtual Stem. // I'm a virtual Leaf. // I'm a non-virtual Leaf. // I'm a virtual Bud. // #include class Root { public: void Print(); protected: virtual void print(); }; inline void Root::Print() { cout << "I'm a virtual "; print(); } void Root::print() { cout << "Root\n"; } class Stem : public Root { protected: virtual void print(); }; void Stem::print() { cout << "Stem.\n"; } class Leaf : public Stem { public: void Print(); protected: virtual void print(); }; inline void Leaf::Print() { cout << "I'm a non-virtual "; print(); } void Leaf::print() { cout << "Leaf.\n"; } class Bud : public Leaf { public: void Print(); protected: virtual void print(); }; inline void Bud::Print() { cout << "I'm a virtual "; print(); } void Bud::print() { cout << "Bud.\n"; } main() { Root* rp; rp = new Root; rp->Print(); rp = new Stem; rp->Print(); rp = new Leaf; rp->Print(); Leaf leaf; leaf.Print(); rp = new Bud; rp->Print(); } -- --------------------------------------------------------------------------- NOTE: USE THIS ADDRESS TO REPLY, REPLY-TO IN HEADER MAY BE BROKEN! Bruce Cohen, Computer Research Lab email: brucec@tekcrl.labs.tek.com Tektronix Laboratories, Tektronix, Inc. phone: (503)627-5241 M/S 50-662, P.O. Box 500, Beaverton, OR 97077