why does using-declaration in class definition sometimes hides names from its base class and sometimes not?

Viewed 91
struct A { int i; };
struct B { int i; };
struct C: A, B {
    using A::i;
    void f() {
        i = 0;
    }
};

This compiles happily. As far as I know, it is because using A::i; hides B::i.

struct A { int i; };
struct B: A {};
struct C: A {};
struct D: B, C {
    using B::i;
    void f() {
        i = 0;
    }
};

But this does not compile, saying error: 'A' is an ambiguous base of 'D'. I don't understand what's the difference between those two. Why using B::i; does not hide C::i here?

Edit: I'm not trying to make something with that design. I know I should use virtual inheritance most of the case. I'm just wondering about the syntax of c++.

Edit: I'm still confusing with answers (which is now deleted) such as "B::i is same as A::i in second example". What I'm wondering is why is that. Where can I find basic syntax rules that makes B::i and A::i same? I have "The C++ Programming Language" of Bjarne Stroustroup, but that book is simply unreadable to me as a non native English user. If you also have the book, I'd appreciate it if you tell me the section of the book describing this problem.

1 Answers

You formed the "Diamond of Death", well-known problem in C++, which is a design error novice programmer produces. Consider change the design. or, If you really wish it to be compiled, try this:

struct A { int i; };
struct B: virtual A {};
struct C: virtual A {};
struct D: B, C {
    using B::i;
    void f() {
        i = 0;
    }
};

Some more detail: In your code, B has its own A inside its instance, and C has its own A inside its instance. By inheriting from both B, C, D has B::A, and C::A inside it. when you trying to assign a value in i, it may be a B::A::i or C::A::i. Therefore ambiguity arises, and compiler complains. My suggestion code is utilizing virtual inheritance, so, in this diamond, A is appearing in D only once, and the ambiguity is resolved.

Addition: If you wish not to use the virtual inheritance, specify what i you are assigning to. ex)B::A::i = 0;

Related