多重虚拟继承:为什么 class 方法没有歧义?

multiple virtual inheritance: why isn't the class method ambiguous?

我在一次在线测试中遇到了以下 c++ 代码。

#include <iostream>

class A
{
public:
    A(int n = 2) : m_n(n) {}

public:
    int get_n() const { return m_n; }
    void set_n(int n) { m_n = n; }

private:
    int m_n;
};

class B
{
public:
    B(char c = 'a') : m_c(c) {}

public:
    char get_c() const { return m_c; }
    void set_c(char c) { m_c = c; }

private:
    char m_c;
};

class C
    : virtual public A
    , public B
{ };

class D
    : virtual public A
    , public B
{ };

class E
    : public C
    , public D
{ };

int main()
{
    E e;
    C &c = e;
    D &d = e;
    std::cout << c.get_c() << d.get_n();

    c.set_n(3);
    d.set_c('b');
    std::cout << c.get_c() << d.get_n() << std::endl;

    return 0;
}

代码输出 a2a3 但我不明白。为什么这个 运行 首先不是 class B 方法不明确?另外class E实际上不是继承的。

如果您尝试 e.get_c(),那将是模棱两可的。

然而,CD接口各只包含一个B,彼此之间一无所知。

您正在通过 cd 引用访问 CD class 的方法,没有歧义。试试这个

std::cout << e.C::get_c() << e.C::get_n() << std::endl;
std::cout << e.D::get_c() << e.D::get_n() << std::endl;

//line below will not compile because here access 'get_c' is ambiguous
//std::cout << e.get_c() << e.get_n() << std::endl;

在这里您将直接通过 e 实例访问 CD classes 的方法。现在最后一行由于调用 e.get_c() 而有歧义,您必须指定 C::D:: 前缀来解决有利于 CD 的歧义方法。

std::cout << e.C::get_c() << e.get_n() << std::endl;
std::cout << e.D::get_c() << e.get_n() << std::endl;

注意:get_n() 前不需要加前缀,因为A 是一个虚拟基class,介于C 和[=13 之间=] 在继承树中。

由于 c 的类型为 C&d 的类型为 D&,因此没有歧义 - CD 都具有一个 B 个子对象。

(cd 字面上指的是 e 各自的子对象——它们不是指“e,而是在不同的类型下”。 )

之所以输出是"a2a3"而不是"a2b3"或"a2a2"是因为A是虚继承的,所以只有一个A E 中的子对象,因此只有一个 n 成员。

CD子对象各有一个B子对象,d.set_c('b');修改d中的子对象,但不修改[=]中的子对象10=].