Preliminary remarks
Your code snippet doesn't compile for another reason: Base
has no access to Time
's foo()
as it is a private member. So the foo1()
causes an error, before you have the reported ambiguity.
If you change Time
to make its member protected, then you can reproduce your error exactly as you describe:
class Time{
protected:
void foo();
};
What's wrong here ?
Base
privately inherits Time
, so that it's members are not expected to be visible to the outside world.
But what could be true for the external world is not true for derived classes. The name lookup rules in the case of derivation say that first the name is looked up in the class hierarchy, then overloading is applied, than only is access control carried out:
10.2/1 Member name lookup determines the meaning of a name (id-expression) in a class scope. Name lookup can result in an
ambiguity, in which case the program is ill-formed. For an
id-expression, name lookup begins in the class scope of this; for a qualified-id, name lookup begins in the scope of the
nested-name-specifier. Name lookup takes place before access
control.
10.2/8 If the name of an overloaded function is unambiguously found, overloading resolution also takes place before access control.
Ambiguities can often be resolved by qualifying a name with its class
name.
As you use multiple inheritance:
Time
:
:
Base Time
\ :
\ :
Child
So you inherit twice a foo()
, once via private inheritance and onve via public. This ambiguity makes the name foo
in foo2()
ambiguous according to the standard, and before access is verified, making your code invalid.
Note that Child sees 2 foo() but ironically can't use none of them: both come via private inherited. So even if you'd resolve the ambiguity, you'd get another error message about accessibility.