I've got a real situation which can be summarized in the following example:
template< typename ListenerType >
struct Notifier
{
void add_listener( ListenerType& ){}
};
struct TimeListener{ };
struct SpaceListener{ };
struct A : public Notifier< TimeListener >
, public Notifier< SpaceListener >
{
};
struct B : TimeListener{ };
int main()
{
A a;
B b;
a.add_listener( b ); // why is ambiguous?
return 0;
}
Why is not obvious to the compiler that B
is a TimeListener
, and therefore the only possible overload resolution is Notifier< TimeListener >::add_listener( TimeListener& )
?
Ambiguity in inheritance can be defined as when one class is derived for two or more base classes then there are chances that the base classes have functions with the same name. So it will confuse derived class to choose from similar name functions. To solve this ambiguity scope resolution operator is used “::”.
Inheritance Ambiguity in C++ In multiple inheritances, when one class is derived from two or more base classes then there may be a possibility that the base classes have functions with the same name, and the derived class may not have functions with that name as those of its base classes.
It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.
Ambiguity in Multiple Inheritance It's because compiler doesn't know which function to call. For example, class base1 { public: void someFunction( ) {....} }; class base2 { void someFunction( ) {....} }; class derived : public base1, public base2 {}; int main() { derived obj; obj.
The lookup rules for member names say that your code is ambiguous, because the name is found in two base classes and therefore the lookup set is invalid. You don't need to be familiar with all the details of lookup sets and merging; the important detail is that both base classes are checked and the name add_listener
is found in both, which creates an ambiguity.
The easy fix is to bring those base class names into A
with using-declarations. This means that both versions of add_listener
are looked up in A
, rather than in the base classes, so there is no merge ambiguity:
struct A : public Notifier< TimeListener >
, public Notifier< SpaceListener >
{
using Notifier<TimeListener>::add_listener;
using Notifier<SpaceListener>::add_listener;
//plus any more base classes
};
Live Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With