4

Can someone explain to me the following compiler error, which says that 'x' is an ambiguous reference?

Why can the compiler not allow this, if it knows that one of those variables is actually inaccessible?

class A {
    int x; // private here
};

class B {
public:
int x; // public here
};

class C : public A, public B {

};

int main() {

    C c;
    c.x = 5; // here is the error

    return 0;
}

Edit: For people who explain to me that private does not mean that it cannot be changed - I know that, and made this simple example below, but this is not the case I was asking about.

//
// the goal is to hack x, y values
//
#include <stdio.h>
#include <memory>

class A {
    int x;
    int _r;
    double y;
public:
    A() { x = 1; y = 0.5; _r = 0; }
    void foo() { printf("x = %d, y = %lf, _r = %d\n", x, y, _r); }
};

int main() {

    struct _B {
        int x = 2;
        double y = 1.5;
    } b;

    A a;

    a.foo();    // gives "x = 1, y = 0.500000, _r = 0"
    memcpy(&a, &b, sizeof(_B)); // where the sizeof B is eq 16 (4 for int, 4 for padding, 8 for double)
    memcpy(&a, &b, sizeof(b.x) + sizeof(b.y)); // that is undefined behaviour, in this case _r is overridden
    a.foo();    // gives "x = 2, y = 1.500000, _r = -858993460" (_r is just a part of floating point y value but with invalid cast)

    return 0;
}
Boann
  • 48,794
  • 16
  • 117
  • 146
  • 1
    Does this answer your question? [c++ Multiple parents with same variable name](https://stackoverflow.com/questions/12255087/c-multiple-parents-with-same-variable-name) – GoodDeeds Jan 25 '20 at 15:22
  • Does this answer your question? [If both base and derive class has a same member variable, how compiler resolve which member is to be called?](https://stackoverflow.com/questions/10397089/if-both-base-and-derive-class-has-a-same-member-variable-how-compiler-resolve-w) – NutCracker Jan 25 '20 at 15:22
  • 3
    On an unrelated note, `class C : public A,B` is not the same as `class C : public A, public B`. – Empty Space Jan 25 '20 at 15:26
  • well the point is that x member variable from class A should be inaccesible from the C class. That is obvious if both 'x' variables have same access rights that would be an error, but it is not this case. – Johny Siemano Kolano Jan 25 '20 at 15:28
  • Mutable Side Effect, yeah thats right, thats the miss spell from me, wanted to make public, public inheritance, but still that is an error, i will edit it – Johny Siemano Kolano Jan 25 '20 at 15:30

2 Answers2

4

Your C contains two x variables. One inherited from each parent class. So it's ambiguous whether you want to assign to the A::x or the B::x. Just because one isn't accessible doesn't mean that the other will be automatically selected. The compiler cannot know if you intended to try to assign to the private A::x (which would then be a different error) or the public B::x.

Also, as noted in comments, class C : public A,B is not the same as class C : public A, public B. In the first case you inherit publicly from A but privately from B (since private inheritance is the default for a class unlike for struct where the default is public inheritance). In the second case you'd inherit publicly from both base classes.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • well yes thats is right, i have just fixed it, because double public inheritance is what i wanted to do, just miss spell from me. But still, i am just curious if there is some feedback from c++ standard about it. Tested it in the clang, gcc, and MS compilators and all reports the same error. Why they do not allow to do this, if the compilator knows that one of it is acctually inaccessible? – Johny Siemano Kolano Jan 25 '20 at 15:35
  • 1
    @JohnySiemanoKolano Because that's how the C++ standard says it should be. – Jesper Juhl Jan 25 '20 at 15:36
  • They are both accessible :) – mfnx Jan 25 '20 at 15:38
  • mfnx, the A::x is not accessible in this case, is declared as private. – Johny Siemano Kolano Jan 25 '20 at 15:51
  • 1
    @JohnySiemanoKolano `private` doesn't make an illegal program legal. – user207421 Jan 25 '20 at 16:00
  • @JohnySiemanoKolano Well, there *are* ways of accessing private member's of classes. Even standard compliant ones. See http://www.gotw.ca/gotw/076.htm and https://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html – Jesper Juhl Jan 25 '20 at 16:01
  • @Jesper Juhl well you acctually dont need template hacking for it, if you know the class skeleton, you can just move or copy the memory to it in the way you want to do so :) just watch out for padding trap – Johny Siemano Kolano Jan 25 '20 at 16:10
0

The compiler checks for ambiguities at compile time. Because ambiguity checking occurs before access control or type checking, so when it has found out that there is an ambiguity the compiler is yet to know the access control assigned to those variables and hence throws an error. Hope that answers your question