关于多重继承和歧义

时间:2016-01-29 22:31:07

标签: c++ c++11 multiple-inheritance ambiguity

在以下示例中:

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的实例导致同样的歧义问题?

5 个答案:

答案 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您继承自s1s2的情况,这两个类都继承自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,这是明确的。