TITLE: Method access and visibility


PROBLEM: krienke@informatik.uni-koblenz.de (Rainer Krienke)

Consider the following code:

class base {
private:
	int i;
public:
	void f(){ i++; }
};

class sub: public base {
public:
	void g () {  f();       }	// A call to base::f()
	void g1() {  base::f(); }	// Aquivalent to g()
	void g2() {  sub:: f(); }	// Shouldn`t my compiler complain at 
					// this point? A sub:: tries to 
					// access a private member of base
};

In my eyes method f() should have base::f() as its signature. 
A call like in g() would actually be a call to base::f().
So why doesn't my compiler complain in g2() when sub::f() is called. 
Why can sub::f() access the private base::i? Moreover there 
actually is no sub::f() definition in the class sub, 
there only is a base::f().


RESPONSE: clamage@Eng.Sun.COM (Steve Clamage), 28 Sept 94

When you call a function as "f()", you get the "f" which is visible in the
current scope. Visibility is determined by looking first in the current
scope, then in the next outer scope, and so on until the identifier "f"
is found. Whatever "f" that is is the one you get.

If you use a scope modifier, as in "X::f()", that does NOT necessarily
mean the function whose name is "X::f", since as you note there might not
be such a function. It means instead to start in the scope of "X" and
use the identifier "f" which is visible from there, using the same visibility
rules as above. Only the starting point is (possibly) different.

In class "sub", there is a function "f" which is visible, and it happens to
be the one defined in class "base". In this case, "sub::f" and "base::f"
refer to the same function. Since "f" is public in base, and sub is publicly
derived from base, there is no problem about access. Nothing private is
being accessed.

If you later add a function "f" to class "sub", then "sub::f" and "base::f"
will no longer refer to the same function. That is why it is not usually a
good idea to use an explicit base-class scope modifier when referring to
something seen from a derived class. If you later add to the derived class,
the code will continue to compile but will refer to an unintended function.

(The obvious exception is when deliberately calling base::f from sub::f, in
which case you must use the qualifier to avoid a recursive call!)



