有人可以解释为什么这段代码中的输出是a2a3吗?

问题描述

我很难理解高级继承概念和多态性。我想了解这是如何在“幕后”进行的。 但是我找不到深入的教程。我在哪里可以学到更多呢? 如果提供教程是题外话(尽管我不考虑这种观点,但要么就这些主题进行了深入探讨,要么没有,但我不确定100%肯定),然后仅解释此代码的幕后故事。就足够了。

// Test.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#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;
}

解决方法

将类A定义为类C和D继承的虚拟类,A的成员成为C和D的成员。它们最终由E继承。A的虚拟属性正确将A类的成员设置为E类的成员而不会发生冲突。另一方面,B不是C和D的虚拟成员。被E继承后。类E中有C:B :: m_c和D:B :: m_c。因此,更改了D:B :: m_c到'b'并没有反映在c.get_c()打印的C:B :: m_c ='a'上。

为显示差异,您可以将代码“ c:set_n(3)” 的最后部分替换为“ e:set_n(3)” 。它也可以正常工作:

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

但是用 e.set_c('b')替换 d.set_c('b')会给成员“ set_c”造成歧义的编译器错误 。因为C类和D类都有两个 set_c

{{1}}