多个虚拟继承:为什么类方法不明确?

时间:2015-09-22 08:28:24

标签: c++ multiple-inheritance virtual-inheritance

我在在线测试中遇到了以下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,但我不明白。为什么这个运行在第一位不是B类方法不明确? E类也几乎没有继承。

3 个答案:

答案 0 :(得分:5)

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

但是,CD接口每个只包含一个B,并且彼此一无所知。

答案 1 :(得分:3)

由于c的类型为C&d的类型为D&,因此没有歧义 - CD只有一个{ {1}}子对象。

Bc字面上引用d的相应子对象 - 它们不是指“e,而是指不同类型”。)< / p>

输出为“a2a3”而不是“a2b3”或“a2a2”的原因是e是虚拟继承的,因此A中只有一个A子对象,因此只有一个E成员。

nC子对象各有一个D子对象,B修改d.set_c('b');中的{@}}但不修改d中的对象。 }。

答案 2 :(得分:1)

您通过CD引用来评估cd类的方法,没有歧义。试试这个

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;

在这里,您将直接通过C实例访问De类的方法。现在最后一行是不明确的,因为调用了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是一个虚拟基类,在继承树中的CD之间进行了剪切。