In the following example:
class A {
public:
virtual void f() { cout << "a" << endl; }
virtual void h() { cout << "A" << endl; }
};
class s1 : public A {
public:
virtual void f() { cout << "s1" << endl; }
};
class s2 : public A {
public:
virtual void h() { cout << "s2" << endl; }
};
class GS : public s1, public s2 {
public:
};
int main()
{
s1 *q = new GS;
q->h();//no problem
GS a;
a.h();//error
}
Why does a.h();
give an ambiguity error yet q->h();
doesn't?
Doesn't *q
have an instance of GS
which should cause the same ambiguity problem?
Your use of multiple inheritance causes two instances of A
to appear in GS
. When you use S1 *q
to access the GS
instance, it follows the A
instance associated with S1
. Since S1
does not implement h()
, the output of q->h()
will be the implementation provided by A
itself.
If you want q->h()
to use the implementation provided by S2
, then you need to create a diamond using virtual inheritance. Doing so will also remove the ambiguity when using a.h()
, since virtual inheritance will cause only one instance of A
to appear in GS
.
class s1 : virtual public A {
public:
virtual void f() { cout << "s1" << endl; }
};
class s2 : virtual public A {
public:
virtual void h() { cout << "s2" << endl; }
};
Name lookup is based on static type not dynamic type. (And it has to be, since it occurs at compile time not run time.)
Because your pointer is of type s1
so the compiler knows to call h()
(inherited from class A
). Try using a pointer of type GS
and you'll get an error for the pointer too. In the case of GS
you are inheriting from s1
and s2
, both classes inherit from A
and thus, multiple(2) definitions of h()
are found which is ambigious. This is the dreaded diamond.
Ok, this is because when the compiler evaluates q->h(), q only has one function named 'h' in its scope since it is of type s1.
When the compiler evaluates a.h(), a has two functions named 'h' in its scope. The one from s1 and the one from s2.
The compiler doesn't know which one you wanted to use, so it throws an error.
*q
doesn't give an ambiguity error because its type is s1*
. This means that the compiler will call s1::h
, which is unambiguous.