Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!cs.utexas.edu!uunet!microsoft!alonzo From: alonzo@microsoft.UUCP (Alonzo Gariepy) Newsgroups: comp.lang.c++ Subject: Re: Implementing virtual functions that return reference to self Keywords: virtual functions, derived classes, extended typechecking Message-ID: <7131@microsoft.UUCP> Date: 27 Jul 89 23:19:12 GMT References: <8975@thorin.cs.unc.edu> Reply-To: alonzo@microsoft.UUCP (Alonzo Gariepy) Organization: Microsoft Corp., Redmond WA Lines: 71 In article <8975@thorin.cs.unc.edu> kelleymt@luther.cs.unc.edu (Michael T. Kelley) writes: | I've been working on a set of classes for manipulating graphics | primitives. For many of the sub-classes, there are members I don't ^^^^ [i.e., goodbye(), below] | want to "stub-out" in the parent class. The problem comes when | grouping redefined functions in the sub-class with functions | not stubbed out in the parent into a single expression: | | #include | | class Base { | public: | Base() { } | virtual Base& hello() { cout << "hello "; return *this; } | }; | | class Derived : public Base { | public: | Derived() { } | Base& hello() { cout << "g'day "; return *this; } // ugh. | void goodbye() { cout << "see ya!\n" } | }; | | main() | { | Derived d; | d.hello().goodbye(); // ERROR: goodbye undefined | } The problem you are looking at is really one of typechecking. If you do have Derived::hello() return a Derived& then your example makes some sense, but what about: Derived d; Base &b = d; b.hello().goodbye(); This would run and return a Derived& but it doesn't make much sense. The semantics you want involve the notion of This (This-Class as opposed to this-object). Your functions become: virtual This& Base::hello() { cout << "hello "; return *this;} and virtual This& Derived::hello() { cout << "g'day "; return *this;} and consider This& Base::somebasefunc() {blah, blah, ...;} This makes these function of identical type and formalizes the idea of passing the invocation type through polymorphic and inherited functions. For example, d.hello(); // Derived::hello() and returns Derived& Base b; b.hello(); // Base::hello() and returns Base& Base &b = d; b.hello(); // Derived::hello() and returns Base& d.somebasefunc(); // Base::somebasefunc() and returns Derived& I think This is a useful notion. It is effectively an automatic cast, but only in circumstances that are clearly safe. The typechecking would not be difficult. Of course the reason for all this is so that I can conveniently say subob.basefunc().subfunc().subfunc().superbasefunc().subfunc(); This is a useful feature that can be added to the language compatibly (except for anyone who has named a class, This) and simplifies things rather than complicating them. Alonzo Gariepy // If Microsoft has an opinion, alonzo@microsoft // they haven't told it to me.