[comp.lang.c++] Why can't access control be used to disambiguate between ba

Tim_CDC_Roberts@cup.portal.com (08/03/89)

In article <9716@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:
> In article <13073@polyslo.CalPoly.EDU>, ttwang@polyslo.CalPoly.EDU
> (Thomas Wang) writes:
> > We need name conflict resolution, because class A may be supplied by 
> > AT&T, and class B may be supplied by IBM.  Both classes come with 
> > compiled object code and class header.  Joe the programmer then must 
> > make class C from class A and class B.  In this case, the modification 
> > and re-compilation of both class A and class B are impossible. 
>
> I don't quite see why this causes a problem.

I have to agree with Mr Wang.  It seems to me that a compiler should be
able to disambiguate the following modification of your example:

    class A { private int x; };
    class B { public int x; };
    class C: A, B { };

    void foo()
    {
        A a;
        B b;
        C c;

        a.x = 3;                // Incorrect -- private
        b.x = 4;                // OK
        c.x = 5;                // Since c.A::x does not exist, as far
                                // as C is concerned, this should NOT
                                // be ambiguous and should be allowed.
        c.A::x = 5;             // Incorrect -- private
        c.B::x = 5;             // OK
    }

Tim_CDC_Roberts@cup.portal.com                | Control Data...
...!sun!portal!cup.portal.com!tim_cdc_roberts |   ...or it will control you.

 

dlw@odi.com (Dan Weinreb) (08/04/89)

In article <20951@cup.portal.com> Tim_CDC_Roberts@cup.portal.com writes:

   I have to agree with Mr Wang.  It seems to me that a compiler should be
   able to disambiguate the following modification of your example:

       class A { private int x; };
       class B { public int x; };
       class C: A, B { };

	   c.x = 5;                // Since c.A::x does not exist, as far
				   // as C is concerned, this should NOT
				   // be ambiguous and should be allowed.

Here's my understanding of why things work the way they do.  As we
have seen from previous postings, the C++ philosophy is NOT that
"c.A::x does not exist".  It does exist.  You're just not allowed to
access it.

That is, what C++ calls "access control" is really "access control",
NOT "name hiding".  It's like a locked safe in a bank; you can't get
into it, but you know it's there.  In your example, both varibles are
visible, and so the reference is ambiguous, even though you are only
granted access to one of them.  The ambiguity is between "yes, here,
you can have the value from class B" and "error, you may not reference
the value from class A", and there's no way know which is the proper
thing for the compiler to generate.

Exactly the same issue arises in SINGLE inheritance as well; this is
not an issue specific to multiple inheritance.  Namely, if I write a
class, with a private data member "a", and then you want to subclass
it, and you happen to choose "a" as the name of a data member, you'll
get an error message from the compiler.  The name "a", although
private, is still apparent to the subclass writer; there is no name
hiding here.

ARK recently pointed out one advantage of this arrangement: if the
base class writer later chooses to make "a" public instead of private,
he need not worry about causing conflicts with existing subclasses.

(Personally, I think that a name-hiding approach would have more
conducive to proper modularity, and appeals to me more.  While
agreeing with ARK's point about the advantage, I think I would have
made the tradeoff the other way.  Of course, there may be other
important language design considerations that I am not aware of; the
implications of such a change could be felt in many places, and might
cause other effects.  Anyway, it's all quite academic at this point.)

Dan Weinreb		Object Design, Inc.		dlw@odi.com

ark@alice.UUCP (Andrew Koenig) (08/05/89)

In article <406@odi.ODI.COM>, dlw@odi.com (Dan Weinreb) writes:

> Exactly the same issue arises in SINGLE inheritance as well; this is
> not an issue specific to multiple inheritance.  Namely, if I write a
> class, with a private data member "a", and then you want to subclass
> it, and you happen to choose "a" as the name of a data member, you'll
> get an error message from the compiler.  The name "a", although
> private, is still apparent to the subclass writer; there is no name
> hiding here.

Not quite.

Member names follow scope rules.  For example:

	class Foo {
	private:
		int a;
	};

	class Bar: public Foo {
	private:
		int a;
	public:
		void zot() { a = 0; }
	};

No problem.  The use of to `a' in Bar::zot() refers unambiguously
to Bar::a.  The fact that Foo::a exists is irrelevant because defining
`a' in class Bar hides Foo::a.

-- 
				--Andrew Koenig
				  ark@europa.att.com