Reputation: 873
I've got an Inheritance problem: Let's say I've got
class Time{
protected:
void foo();
};
and also
class Base: private Time{
void foo1(){ foo(); }
};
class Child: public Base, private Time{
void foo2(){ foo(); }// here my compiler says that foo is ambiguous
};
why is foo() ambiguous, if the inheritance of Time in Base is private?
PS. Just&only for those who need to see the full code, here is the GitHub Project: https://github.com/huntekah/Interior_decorator-OpenGL_Project/blob/master/Grafika-OpenGL/Interior_decorator/Display.cpp#L133 class Time( utilities directory ) is inherited by ControlObjects and ControlCamera, both of which are the base for Controls. Display inherits Controls , and additionally Time. commented line shows a place where SetDeltaTime() is ambiguous;
Upvotes: 2
Views: 1594
Reputation: 3911
there's another error in your code: class base inherits privately from class Time and class Child inherits again privately from class time!!!
the law of inheritance:
class Time
{};
class Base : private Time
{};
class Child : public Base, private Time
{};
Base has a copy of class Time because it inherits from it.
child has a copy of class Base because it inherits from it.
*** Child has a copy of class Time because its parents (Base) has this copy.
if Child tries to inherit explicitly from class Time will issue a compile-time-error: error C2584: 'Child' : direct base 'Time' is inaccessible; already a base of 'Base'
Upvotes: 1
Reputation: 73577
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.
Upvotes: 0