Reputation: 56547
Consider the code
struct Base{};
struct Derived: public Base{};
struct A: public Base{};
struct B: public A, public Base{};
struct C: public A, public Derived{}; // why no ambiguity here?
int main() {}
The compiler (g++5.1) warns that
warning: direct base
'Base'
inaccessible in'B'
due to ambiguitystruct B: public A, public Base{};
I understand this, Base
is duplicated in B
.
Why is there no warning for C
? Doesn't C
inherit from both A
and Derived
, which both inherit from Base
?
Why adding virtual
struct Derived: virtual Base{};
results now in both B
and C
emitting warnings, live on Wandbox
warning: direct base
'Base'
inaccessible in'B'
due to ambiguitystruct B: public A, public Base{};
warning: direct base
'Base'
inaccessible in'C'
due to ambiguitystruct C: public A, public Derived{};
Upvotes: 10
Views: 3468
Reputation: 1946
There are no ways to access unambiguously to Base members in "B" whereas it's possible in "C", as illustrated in the following code:
#include <iostream>
using namespace std;
struct Base
{
void print()
{
cout << "Base" << endl;
}
};
struct Derived : public Base {};
struct A : public Base
{
void print()
{
cout << "A" << endl;
}
};
struct B : public A, public Base
{
void print()
{
A::print();
//error (ambiguous), no way to access to Base::print => warning
//Base::print();
}
};
struct C : public A, public Derived
{
void print()
{
A::print();
Derived::print(); // Not Ambiguous, it's the Base inherited by 'Derived' which is used.
// Still an error but you can access print indirectly through "Derived" => no warning needed
//Base::print();
}
};
int main()
{
B b;
b.print();
C c;
c.print();
return 0;
}
Upvotes: 2
Reputation: 119144
In B
, it's impossible to refer to members of the Base
subobject inherited directly. Consider:
struct Base {
int x;
};
struct B: public A, public Base {
void foo() {
int& x1 = A::x; // OK
int& x2 = x; // ambiguous
// no way to refer to the x in the direct base
}
};
In C
this is not a problem. Both x
's can be referred to using qualified names:
struct C: public A, public Derived {
void foo() {
int& x1 = A::x; // OK
int& x2 = Derived::x; // OK
}
};
So the warning you get is one that only makes sense when a direct base is also inherited through another path.
For your second question, I couldn't reproduce the warning with C
on Coliru with g++-5.1.
Upvotes: 2