brucec@phoebus.phoebus.labs.tek.com (Bruce Cohen;;50-662;LP=A;) (09/14/90)
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 <stream.h>
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