Path: utzoo!attcan!uunet!decwrl!sun-barr!newstop!sun!amdahl!key!perry From: perry@key.COM (Perry The Cynic) Newsgroups: comp.std.c++ Subject: Re: Inheritance in cfront and g++ Summary: C++ rules are proper Keywords: overloading Message-ID: <2056@key.COM> Date: 20 Aug 90 17:36:49 GMT References: <1990Aug17.141710.5004@aucs.uucp> <38219@ucbvax.BERKELEY.EDU> Reply-To: perry@arkon.key.COM (Perry The Cynic) Organization: Key Computer Laboratories, Fremont Lines: 65 In article <38219@ucbvax.BERKELEY.EDU> jbuck@galileo.berkeley.edu (Joe Buck) writes: > [Quote deleted, complaining that a function member definition hides > all functions of that name in parent classes, not just the one with > the specific parameter profile. Notes that g++ does not do that.] > > Unfortunately, E&S (which is the base document for the standard) mandates > the cfront behavior. Unless this is changed, you can expect future > versions of g++ to be changed to conform (since Michael Tiemann has > promised to track the standard). > > Stroustrup justifies this by pointing out cases where the g++ behavior > might lead to surprises when new functions are added, but I'm not > swayed by his argument. > Actually the argument goes like this: a group of overloaded functions is really intended to provide different *variants* of one functionality. Two functions without closely tied purpose and operation should not be overloaded (within the same class). Thus, if you redefine a function in a descendant class, you should make damn sure that the close relationship between the function variants in the parent is not violated (by failing to override one of them). At minimum, you should add inline members to the child to explicitly confirm that some variants of the parent are still applicable unchanged. Let's say there's this class Frob { public: void frobMe(void); void frobMe(int howOften); }; Frob frobber; where the frobMe(void) is trying to guess how often you want to frob, and then calls frobMe(int). If you create class MyFrob : public Frob { public: void frobMe(int moreOften); }; MyFrob frobber; (and neglect to redefine frobMe(void) as well), then somebody who is used to deal with a Frob may keep calling frobber.frobMe(void), if only because he didn't change his source but you changed yours. Of course frobMe(void) still calls the old frobMe(int), which is likely NOT what you intended. As things stand, the unsuspecting user of frobMe(void) will find that his source suddenly stops compiling, and he'll probably come battering down your door to demand an explanation. Of course you can argue that frobMe(int) should really be virtual. Maybe the rule should be relaxed to specify that only redeclaring non-virtual functions performs full hiding, but that would be another piece of user-visible (and, probably, user-confusing) complexity. As it stands, you can avoid these problems by judicious choice of (function) names. -- perry P.S.: I've worked in ADA, where relaxed one-variant-at-a-time overloading rules are in effect. Let me tell you that it's no fun trying to track down *which* fooBar(xyz) the compiler decided to call this time, especially with implicit conversions clouding the issue. By current C++ rules, the first (inner-most) class defining any fooBar member *must* be the one containing the thing you called. -- -------------------------------------------------------------------------- Perry The Cynic (Peter Kiehtreiber) perry@arkon.key.com ** What good signature isn't taken yet? ** {amdahl,sgi,pacbell}!key!perry