Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!uunet!samsung!usc!apple!hercules!sparkyfs!mckenney From: mckenney@sparkyfs.istc.sri.com (Paul Mckenney) Newsgroups: comp.std.c++ Subject: Re: Separate Decl of Private Member Fcn Message-ID: <32537@sparkyfs.istc.sri.com> Date: 8 Aug 90 17:16:40 GMT References: <259400001@inmet> <32527@sparkyfs.istc.sri.com> Reply-To: mckenney@perth.itstd.sri.com.UUCP (Paul E. McKenney) Organization: SRI International, Menlo Park, CA 94025 Lines: 114 In article mcgrath@homer.Berkeley.EDU (Roland McGrath) writes: >In article <32527@sparkyfs.istc.sri.com> mckenney@sparkyfs.istc.sri.com (Paul Mckenney) writes: > In article <259400001@inmet> stt@inmet.inmet.com writes: > > > >It seems to be a major maintenance/recompilation headache that any > >private utility function which is to be used to implement > >public member functions must be declared in the class declaration, > >either as a private member function, or as a friend. > > [ . . . ] > >This issue is discussed in E&S 9.3, bottom of page 174, but > >I find the argument unconvincing: > > "Why can't functions be added to a class after the end > > of the class declaration? If this were allowed, a user > > could gain access to a class simply by declaring an additional > > function." > >[ . . . ] Where is the danger? > > The danger is that a programmer could hijack a call that was intended > to invoke a base-class member function: > > [...] > > This hijacking could be hidden deep inside a large, complex system and > be very difficult to find, especially if classes A and B had been thoroughly > debugged and were hence presumed innocent. > >This a good argument for programmers not doing this sort of thing, since it may >make their lives more difficult down the road. Why, however, should they be >prohibited from doing it? Sure sounds like a victimless crime to me.... In a single-programmer project, one can certainly argue that the only possible victim is the perpetrator. In larger projects with many participants, retribution does not necessarily so surely and swiftly descend upon the perpetrator. In addition, note that the use of derivation and virtual functions provides a safer and more ``socially acceptable'' way of getting this effect in many cases: #include class A { public: virtual void do_the_A_thing() { cout << "Doing the A thing.\n"; } }; class B : public A { public: void do_the_B_thing() { cout << "Doing the B thing.\n"; do_the_A_thing(); } }; class take_me_to_Baghdad : public B { public: void do_the_A_thing() { cout << "Hijacked to Baghdad!\n"; } }; main() { A a; B b; take_me_to_Baghdad c; cout << "a.do_the_A_thing();\n"; a.do_the_A_thing(); cout << "b.do_the_B_thing();\n"; b.do_the_B_thing(); cout << "c.do_the_B_thing();\n"; c.do_the_B_thing(); } The output of this program is: a.do_the_A_thing(); Doing the A thing. b.do_the_B_thing(); Doing the B thing. Doing the A thing. c.do_the_B_thing(); Doing the B thing. Hijacked to Baghdad! The approach shown in this program is safer for two reasons: (1) the ``virtual'' keyword on ``do_the_A_thing()'' has explicitly warned the programmer that this member function can be overridden in a derived class, and (2) variables declared to be of class A or class B are not affected by the addition of class take_me_to_Baghdad. Please note that there are other problems with the proposed modification. Suppose that one compilation unit adds one member function to a class, and another compilation unit adds a different function. Suppose that one or both of these are virtual functions. Suppose that a reference to an object belonging to the abused class is passed from one of the compilation units to the other. In summary, I feel that the proposed modification encourages dangerous practices and provides few, if any, additional capabilities beyond those of the existing language. Thanx, Paul