3

The following code:

class A1 {
public:
    int x;
};
class A2 {
private:
    int x() { return 67; }
};

class M : public A1, public A2 {};

int main() {
    M m;
    m.x;
}

Compiles with error:

error C2385: ambiguous access of 'x'
note: could be the 'x' in base 'A1'
note: or could be the 'x' in base 'A2'

But why? only A1::x should be visible to M. A2::x should be purely local.

curiousguy
  • 8,038
  • 2
  • 40
  • 58
tower120
  • 5,007
  • 6
  • 40
  • 88

1 Answers1

5

In C++, name-lookup happens before member access checking is performed. Hence, name-lookup (Unqualified in your case) finds two names, and that's ambiguous.

You can use a qualified name to disambiguate:

int main() {
    M m;
    m.A1::x;     //qualifed name-lookup
}
WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
  • 1
    @tower120, no. This isn't related to ADL. [Koenig Lookup](http://en.cppreference.com/w/cpp/language/adl) comes into play when doing unqualifed lookups for non-member functions – WhiZTiM Feb 12 '17 at 17:01
  • By the way, is this something historical, or this is by the design (for something)? For me, at first, this looked like a compiler bug, but now it looks like a language bug :) – tower120 Feb 12 '17 at 17:17
  • 1
    No, it's not a language bug. It is a problem of your expecting access control to affect name lookup. If access control affected name lookup (e.g. changed what match was acceptable) then it would be easy (intentionally or, worse, accidentally) to significantly change behaviour of working code in unexpected ways by simply changing a `private` to a `public` or vice versa. Better to alert the programmer to ambiguity (as happened to you) than to have code which is brittle in the face of small changes. – Peter Feb 18 '17 at 04:45
  • 3
    This is bogus argument. Changing access level is not a "small change", and you will get an expected error when there is really one. The same issue affects simple class inheritance. It breaks the class encapsulation logic, since you define a private member in the base class, and the derived class can't use that name freely any more. – jj99 Dec 07 '17 at 19:51