在以下示例中:
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
}
为什么a.h();
会出现歧义错误,q->h();
却没有?
*q
是否有GS
的实例导致同样的歧义问题?
答案 0 :(得分:4)
名称查找基于静态类型而非动态类型。 (它必须是,因为它发生在编译时而不是运行时。)
答案 1 :(得分:4)
您使用多重继承会导致A
中出现两个GS
个实例。当您使用S1 *q
访问GS
实例时,它会跟随与A
关联的S1
实例。由于S1
未实现h()
,q->h()
的输出将是A
本身提供的实现。
如果您希望q->h()
使用S2
提供的实现,则需要使用虚拟继承创建菱形。这样做也会消除使用a.h()
时的歧义,因为虚拟继承只会导致A
中出现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; }
};
答案 2 :(得分:3)
因为指针的类型为s1
,所以编译器知道调用h()
(继承自类A
)。尝试使用GS
类型的指针,你也会得到指针错误。对于GS
您继承自s1
和s2
的情况,这两个类都继承自A
,因此找到了h()
的多个(2)定义这是一个暧昧的。这是dreaded diamond。
答案 3 :(得分:1)
好的,这是因为当编译器评估q-&gt; h()时,q在其范围内只有一个名为'h'的函数,因为它的类型为s1。
当编译器计算a.h()时,a在其作用域中有两个名为“h”的函数。来自s1的那个和来自s2的那个。
编译器不知道您要使用哪一个,因此会抛出错误。
答案 4 :(得分:1)
*q
不会出现歧义错误,因为其类型为s1*
。这意味着编译器将调用s1::h
,这是明确的。