pal@xanadu.wpd.sgi.com (Anil Pal) (12/08/90)
I am posting this for Martin Hitz, who does not have posting access to the net. Please send e-mail replies to Martin at hitz@csi.UOttawa.CA. Note: I checked that this is the neahiour of cfront 2.o also, and indeed is explicitly stated in the ARM (p.255, section 11.6). Martin would like to raise the issue for discussion, hence I am posting to comp.lang.c++ and comp.std.c++. -- Anil A. Pal, Silicon Graphics, Inc. pal@sgi.com (415)-335-7279 <===== Begin forwarded message =====> From hitz@csi.UOttawa.CA Tue Dec 4 09:47:20 1990 Date: Tue, 4 Dec 90 12:43:56 EST From: hitz@csi.UOttawa.CA (Martin Hitz) Message-Id: <9012041743.AA22998@csi.UOttawa.CA> To: pal@csi.UOttawa.CA Subject: comp.lang.c++ Status: RO I find it awkward that it is possible (at least with g++ and Zortech 2.0) to implicitely call a private member function via the virtual mechanism as in the following example: class B { public: virtual void f() { cout << "B\n"; } }; class D: B { void f() { cout << "D\n"; } }; main() { D d; B& b = d; b.f(); // prints "D" } My opinion is that this shouldn't be possible, i.e. the compiler should complain about the private version of f() in the derived class D. Any comments? Best regards, Martin Hitz hitz@csi.UOttawa.CA
jimad@microsoft.UUCP (Jim ADCOCK) (12/19/90)
In article <1990Dec7.205909.14021@relay.wpd.sgi.com> hitz@csi.UOttawa.CA writes: |I am posting this for Martin Hitz, who does not have posting access to the net. |Please send e-mail replies to Martin at hitz@csi.UOttawa.CA. | |Note: I checked that this is the neahiour of cfront 2.o also, and |indeed is explicitly stated in the ARM (p.255, section 11.6). Martin |would like to raise the issue for discussion, hence I am posting to |comp.lang.c++ and comp.std.c++. |I find it awkward that it is possible (at least with g++ and Zortech 2.0) |to implicitely call a private member function via the virtual mechanism as |in the following example: | | class B { | public: | virtual void f() { cout << "B\n"; } | }; | | class D: B { | void f() { cout << "D\n"; } | }; | | main() | { | D d; | B& b = d; | b.f(); // prints "D" | } | |My opinion is that this shouldn't be possible, i.e. the compiler |should complain about the private version of f() in the derived |class D. | |Any comments? First, I think D needs to derive from a public B otherwise your compiler ought to prohibit the implied coercion of a D ref to a B ref. If you don't mean for B to be a public base, then this discussion is not an issue -- your compiler ought to prohibit it. Is this a point of confusion? Next, for comparison, I've added a function g() below for which I've tried to adjust access control. (Your C++ compiler should prohibit this attempt) For reference, what section 11.6 says is : "The access rules (sec11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it." So compilers indeed ought to accept this program [given D inherits publicly] as you suggest. The question then, is should this rule be changed, and if so, how? Note that some people might actually consider this definition a "feature." B might require some low level methods that it doesn't generally make sense to expose in D, but which are methods that a class D needs to implement in order for B to work correctly. An example pops to mind: Let f() return a class's metaclass representation. At the primitive level we desire to allow people access to runtime type information, but at a higher programming level we want to prohibit such access -- lest programmers fall into the bad habit of programming based on exact type. At the primitive level however, low level functionality such as file I/O needs access to exact type information, so it makes sense to allow access at the base class level. But D needs to override f() in order to return D's correct metaclass information. Voila -- the access to virtual functions rules aren't a bug, their a feature! 1/2 :-) Pragmatically, one might note that class B may be compiled long before D, and therefor the only way to prohibit access to virtual D::f() is to prohibit conversion of a D ref to A B ref. One might ask then if the assignment of a D ref to B ref shouldn't require an explicit conversion? Still, I think when D inherits from a public B, it is stating that a D can be used as a B. This is only possible if all B's public members remain accessible. If you don't want a D to be usable as a B, inherit B privately, and use access control to promote those methods of B to public access that you wish D to support. Compilers then will correctly prohibit conversion of a D to a B. I recommend no change. // comparison of attempt to change access control verses overloaded virtual // function follows [shouldn't compile]: class B { public: virtual void f() { } virtual void g() { } }; class D: public B { private: void f() { } B::g; }; main() { D d; B& b = d; b.f(); b.g(); }