budd@mist.cs.orst.edu (Tim Budd) (05/30/90)
When using inheritance, particularly multiple inheritance, it seems I often miss the ability to do renaming, as in Eiffel. Expanding on the syntax used to create pure virtual functions, it would be nice to do something like the following: class foo : public bar, pubic baz { ... void gak(int i) = bar::geek; .. } where geek is a method defined in bar which takes the same argument list as gak. As it stands, now I have to do something like the following class foo : public bar, pubic baz { ... void gak(int i) { bar::geek(i); } .. } which is arguably no less readable, but does introduce the run-time overhead of one additional function invocation.
lord@yellowsub.sgi.com (Tom Lord) (05/30/90)
In article <18591@orstcs.CS.ORST.EDU> budd@mist.CS.ORST.EDU (Tim Budd) writes: >When using inheritance, particularly multiple inheritance, it seems I often >miss the ability to do renaming, as in Eiffel. > >[...] As it stands, now I have to do something like the following > >class foo : public bar, pubic baz { > ... > void gak(int i) { bar::geek(i); } > .. >} > >which is arguably no less readable, but does introduce the run-time >overhead of one additional function invocation. This should have no extra overhead at all. That is the point of inline functions. Whatever system your language has for resolving `name clashes' in cases like this is definately going to be wrong. Providing rename operators to sprinkle throughout declarations is quirky at best. Writing code to resolve the abiguities is the most general, and simplest solution. Having your compiler do inline optimizations for this code is a pretty good impementation strategy. -t
steve@taumet.COM (Stephen Clamage) (05/31/90)
In article <18591@orstcs.CS.ORST.EDU> budd@mist.CS.ORST.EDU (Tim Budd) writes: > void gak(int i) { bar::geek(i); } >introduce[s] the run-time overhead of one additional function invocation. I know of no C++ compiler which would not inline this member function, and it seems unlikely that any ever would refuse to do so. It seems unnecessary to introduce a new language feature, thus complicating *all* compilers, to make things simpler for users stuck with bad compilers. If your local C++ compiler won't inline such a simple function (meaning no overhead whatsoever), try to get another one. Such a compiler is bound to be woefully deficient in other ways. -- Steve Clamage, TauMetric Corp, steve@taumet.com
jimad@microsoft.UUCP (Jim ADCOCK) (06/01/90)
In article <18591@orstcs.CS.ORST.EDU> budd@mist.CS.ORST.EDU (Tim Budd) writes: >When using inheritance, particularly multiple inheritance, it seems I often >miss the ability to do renaming, as in Eiffel. > >Expanding on the syntax used to create pure virtual functions, it would be >nice to do something like the following: > >class foo : public bar, pubic baz { > ... > void gak(int i) = bar::geek; > .. >} > >where geek is a method defined in bar which takes the same argument list as >gak. As it stands, now I have to do something like the following > >class foo : public bar, pubic baz { > ... > void gak(int i) { bar::geek(i); } > .. >} > >which is arguably no less readable, but does introduce the run-time >overhead of one additional function invocation. There shouldn't be one additional function invocation in the example you give, since gak(int i) is an inline function. Try compiling and looking at the code the following simple example generates. On my system [as in all C++ systems -- I think!] renaming causes no extra code to be generated. extern "C" { #include <stdio.h> } class BASE { public: virtual void Print(); }; void BASE::Print() { printf("BASE@ %lX\n",(long)this); } class FOO: public BASE { public: void BASE_Print() { BASE::Print(); } void Print(); }; void FOO::Print() { printf("FOO @ %lX\n",(long)this); } class BAR: public BASE { public: void Print(); }; void BAR::Print() { printf("BAR @ %lX\n",(long)this); } class FOOBAR: public FOO, public BAR { public: void FOO_Print() { FOO::Print(); } void BAR_Print() { BAR::Print(); } void Print(); }; void FOOBAR::Print() { printf("FOOBAR @ %lX\n",(long)this); } int main() { FOOBAR foobar; foobar.BASE_Print(); foobar.FOO_Print(); foobar.BAR_Print(); foobar.Print(); printf("\n"); FOOBAR* pfoobar = new FOOBAR; pfoobar->BASE_Print(); pfoobar->FOO_Print(); pfoobar->BAR_Print(); pfoobar->Print(); }
roger@procase.UUCP (Roger H. Scott) (06/01/90)
Newsgroups: comp.lang.c++ Subject: Re: renaming Summary: Expires: References: <18591@orstcs.CS.ORST.EDU> <228@taumet.COM> Sender: Reply-To: roger@procase.UUCP (Roger H. Scott) Followup-To: Distribution: Organization: proCASE Corporation, Santa Clara, CA Keywords: In article <228@taumet.COM> steve@taumet.UUCP (Stephen Clamage) writes: >In article <18591@orstcs.CS.ORST.EDU> budd@mist.CS.ORST.EDU (Tim Budd) writes: >> void gak(int i) { bar::geek(i); } >>introduce[s] the run-time overhead of one additional function invocation. > >I know of no C++ compiler which would not inline this member function, >and it seems unlikely that any ever would refuse to do so. It seems >unnecessary to introduce a new language feature, thus complicating *all* >compilers, to make things simpler for users stuck with bad compilers. > >If your local C++ compiler won't inline such a simple function (meaning >no overhead whatsoever), try to get another one. Such a compiler is >bound to be woefully deficient in other ways. >-- > >Steve Clamage, TauMetric Corp, steve@taumet.com Don't you guys *build* C++ compilers? Consider the following: #define redefine struct Base { ... virtual void f(); void implementation1_of_f(); void implementation2_of_f(); }; struct Der1 : public Base { redefine void f() {implementation1_of_f();} }; struct Der2 : public Base { redefine void f() {implementation2_of_f();} }; Are you telling me that you are going to inline Der1::f and Der2::f, both of which are *virtual*? Another example (with MI): struct AbstractThing { ... virtual void f(); }; struct Thing1Implementation { void do_that_there_f_stuff(); ... }; struct Thing2Implementation { void do_that_there_f_stuff(); ... }; struct Thing1 : public AbstractThing, public Thing1Implementation { redefine void f() {do_that_there_f_stuff();} }; struct Thing2 : public AbstractThing, public Thing2Implementation { redefine void f() {do_that_there_f_stuff();} }; Again, how are Thing1::f and Thing2::f going to be inline? It seems like a reasonable generalization of the syntax (and semantics?) of pure virtual functions would be to allow: struct Thing1 : public AbstractThing, public Thing1Implementation { redefine void f() = do_that_there_f_stuff; }; where the "initializer" of the (member) function declaration would be required to be type compatible with the thing that it is initializing, i.e. a member function of the same class or a public base that took the same arguments and returned the same type. The implementation of this is trivial - put the address of the "initializing" function into the vtbl rather than that of a new function.
cline@cheetah.ece.clarkson.edu (Marshall Cline) (06/02/90)
In article <156@logo.procase.UUCP> roger@procase.UUCP (Roger H. Scott) writes: > It seems like a reasonable generalization of the syntax (and semantics?) of > pure virtual functions would be to allow: > struct Thing1 : public AbstractThing, public Thing1Implementation { > redefine void f() = do_that_there_f_stuff; > }; Hmmmm. But what does this do to the conformance requirement of subtypes? You want to change the language, the only benefit of this new language feature being to avoid at most one virtual function call, and the cost of the feature being that publically derived subclasses will no longer will have the same public interface. Hmmmm. I know that subtype conformance isn't important to everyone, but please don't break it for those of us who like to say `is-a'! Marshall Cline -- ============================================================================== Marshall Cline / Asst.Prof / ECE Dept / Clarkson Univ / Potsdam, NY 13676 cline@sun.soe.clarkson.edu / Bitnet:BH0W@CLUTX / uunet!clutx.clarkson.edu!bh0w Voice: 315-268-3868 / FAX: 315-268-7600 Career search in progress; ECE faculty; research oriented; will send vita. ==============================================================================
roger@procase.UUCP (Roger H. Scott) (06/03/90)
In article <CLINE.90Jun2011023@cheetah.ece.clarkson.edu> cline@sun.soe.clarkson.edu (Marshall Cline) writes: >In article <156@logo.procase.UUCP> roger@procase.UUCP (Roger H. Scott) writes: > >> It seems like a reasonable generalization of the syntax (and semantics?) of >> pure virtual functions would be to allow: >> struct Thing1 : public AbstractThing, public Thing1Implementation { >> redefine void f() = do_that_there_f_stuff; >> }; > >Hmmmm. But what does this do to the conformance requirement of subtypes? >You want to change the language, the only benefit of this new language >feature being to avoid at most one virtual function call, and the cost of >the feature being that publically derived subclasses will no longer will >have the same public interface. Hmmmm. How do you figure? I think you are reading something into my proposal that is not there. In the example above Thing1Implementation::do_that_there_f_stuff() *is* inherited by Thing1 (not that this fact is likely to be relevant, given that Thing1Implementation is not by itself very useful or interesting), so: Thing1 *p = ...; p->do_that_there_f_stuff(); would be allowed, as well as p->f(); // which happens to do the same thing > >I know that subtype conformance isn't important to everyone, but please >don't break it for those of us who like to say `is-a'! I wouldn't dream of messing with such a thing. I don't have any problems with the type system, and am not out to change it either deliberately or accidentally. By the way, you are wrong about "the only benefit ... being to avoid one virtual function call". There is also argument passing, which in C++ can be non-trivial in the case of objects with X::X(const X&) defined. For instance, imagine a little reference-counted pointer class. Everytime an instance of such a class is passed to a function the object is copied and the reference count must be bumped. Then there's returning values ...