Topic: Q: Public access to private member functions via virtual functions.
Author: jason@cygnus.com (Jason Merrill)
Date: 06 Mar 1995 23:54:07 GMT Raw View
>>>>> Roland Radtke <Roland.Radtke@arbi.informatik.uni-oldenburg.de> writes:
> I happened across some behaviour which struck me as rather weird:
> the ANSI C++ Standard to come explicitly allows public access to
> private member functions if the member function can be interpreted
> as overriding a virtual member in some class higher up the inheritance
> graph. Why is that so?
Because access control is checked statically in C++.
Jason
Author: Roland.Radtke@arbi.informatik.uni-oldenburg.de (Roland Radtke)
Date: Mon, 6 Mar 1995 14:06:50 GMT Raw View
Hi !
I happened across some behaviour which struck me as rather weird:
the ANSI C++ Standard to come explicitly allows public access to
private member functions if the member function can be interpreted
as overriding a virtual member in some class higher up the inheritance
graph. Why is that so? I believe it's very practicable in writing
compilers but might prove a possible problem if people start reusing
classes heavily.
My mistaken bug report and the answer to it follow (I don't have much
time with the CeBIT approaching).
So long,
Roland.
----------------------------------------------------------------------------------
Hi there,
Thanks for the bug report.
This is what is required by the draft ANSI/ISO C++ standard -
10.3 Virtual functions [class.virtual]
1 Virtual functions support dynamic binding and object-oriented
programming. A class that declares or inherits a virtual function is
called a polymorphic class.
2 If a virtual member function vf is declared in a class Base and in a
class Derived, derived directly or indirectly from Base, a member
function vf with the same name and same parameter list as Base::vf
is declared, then Derived::vf is also virtual (whether or not it is
so declared) and it overrides51) Base::vf. For convenience we say
that any virtual function overrides itself. Then in any well-formed
class, for each virtual function declared in that class or any of its
direct or indirect base classes there is a unique final overrider
that overrides that function and every other overrider of that
function.
__________________________
51) A function with the same name but a different parameter list (see
13) as a virtual function is not necessarily virtual and does not
override. The use of the virtual specifier in the declaration of an
overriding function is legal but redundant (has empty semantics).
[*****] Access control (11) is not considered in determining
overriding. [*****]
Regards,
Rohan
------------------------------------------------------------------------
Excerpts from BugReport.Gnu: 4-Mar-95 no subject (file transmission)
Roland Radtke@arbi.infor (3435)
> Hello!
> I'd like to report something of which I'm not quite sure
> whether it's a bug or not. The behaviour I find strange
> is not only specific to g++ but also occurs using the standard
> Sun Compiler "SC1.0"(whatever that is...).
> I believe I found a way of accessing private member functions of
> an inherited class.
> Here's my gcc and machine specification:
> tracy:~/tmp/test 114) g++ -v
> gcc -v
> Reading specs from /usr/local/lib/gcc-lib/sparc-sun-sunos4.1.3/2.6.3/specs
> gcc version 2.6.3
> tracy:~/tmp/test 117) uname -a
> SunOS tracy 4.1.2 2 sun4c
> Here is a simple sample of a program exploiting the strange behaviour:
> -test.hh---------------------------------------------------------------
> class A {
> public:
> virtual void test() =0;
> };
> class B : public A {
> private:
> void test();
> };
> -----------------------------------------------------------------------
> Although I cannot find a place in the ARM explicitly mentioning what
> to do in such situations, I am strongly convicted that the derived
> class B should contain a public member void test(). Yet, no error
> occurs during compilation, and, worse: main() can call B's private
> test() function, as is shown by compiling and executing the following
> program.
> -test.cc---------------------------------------------------------------
> #include "test.hh"
> #include <iostream.h>
> void B::test() {
> cout << "B::test() called.\n";
> }
> void main() {
> A* a;
> a=new B;
> a->test();
> }
> -----------------------------------------------------------------------
> Here's what happens:
> tracy:~/tmp/test 134) g++ -o test test.cc
> tracy:~/tmp/test 135) test
> B::test() called.
> CC behaves alike:
> tracy:~/tmp/test 136) CC -o test test.cc
> tracy:~/tmp/test 137) test
> B::test() called.
> The conflict with "proper" (in)visibility of inherited functions
> appears more clearly in the following context:
>
> -test2.hh---------------------------------------------------------------
> class A {
> public:
> virtual void test() =0;
> };
> class B : public A {
> private:
> void test();
> };
> class C : public B {
> public:
> void test2();
> };
> -----------------------------------------------------------------------
> -test2.cc---------------------------------------------------------------
> #include "test2.hh"
> #include <iostream.h>
> void B::test() {
> cout << "B::test() called.\n";
> }
> void C::test2() {
> #ifdef DIRECT
> test();
> #elif INDIRECT
> this->test();
> #elif ERROR
> A::test();
> #else
> ((A*)this)->test();
> #endif
> }
> void main() {
> C c;
> c.test2();
> }
> -----------------------------------------------------------------------
> The results are as follows:
> tracy:~/tmp/test 142) g++ -DDIRECT -o test test2.cc
> test2.cc: In method `void C::test2()':
> test2.cc:4: method `void B::test()' is private
> test2.cc:10: within this context
>
> tracy:~/tmp/test 143) g++ -DINDIRECT -o test test2.cc
> test2.cc: In method `void C::test2()':
> test2.cc:4: method `void B::test()' is private
> test2.cc:12: within this context
>
> tracy:~/tmp/test 144) g++ -DERROR -o test test2.cc
> /usr/tmp/cca012171.o(.text+0x48): undefined reference to `A::test(void)'
> collect2: ld returned 1 exit status
>
> tracy:~/tmp/test 145) g++ -o test test2.cc
> tracy:~/tmp/test 146) test
> B::test() called.
> g++ refuses to access test() in any conventional way, but calls B's
> private test() method if treated as an A pointer.
> So: Is this a bug or a feature ? :)
> So long,
> and keep up the good work,
> Roland.