Johny Siemano Kolano
Johny Siemano Kolano

Reputation: 137

Why is the x member variable ambiguous?

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;
}

Upvotes: 5

Views: 788

Answers (2)

Abhishek Sakharkar
Abhishek Sakharkar

Reputation: 19

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

Upvotes: 0

Jesper Juhl
Jesper Juhl

Reputation: 31475

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.

Upvotes: 4

Related Questions