输出变为a2a3而不是a2b3

时间:2013-01-31 10:33:01

标签: c++ multiple-inheritance

我理解的是,在E对象中,C和D对象分别由c和d引用。但是我无法理解为什么d.set_c('b')无法将B.m_c初始化为'b',因为c.set_n(3)能够将A.m_n的值更改为3。

    #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;  //object of E is created
        C &c = e; //c is used to refrence C object in E Object 
        D &d = e; //c and d has same inheritance structure 
        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;
    }

3 个答案:

答案 0 :(得分:3)

让我们看看你的类结构,如果你创建一个E的实例,你最终会得到一个如下所示的对象层次结构:

 class B   class A   class B
     \       / \       /
      \     /   \     /
       \   /     \   /
      class C   class D
          \       /
           \     /
            \   /
           class E

您会看到B有两个实例,但只有A的一个实例。这是因为虚拟继承。 CD都使用虚拟继承从A继承,因此A中只有e的一个实例。

现在让我们看一下用户代码:

E e;
C &c = e; // reference C in the object hierarchy of E
D &d = e; // reference D in the object hierarchy of E

c.set_n(3); // set the value in the only instance of A in E
d.set_c('b'); // set the value of one of the two instances of B in your e

std::cout << c.get_c(); // print the value in the other instance of B in e
                        // not the one you set before
std::cout << d.get_n(); // print the value of the only instance of A in e
                        // this got changed before

答案 1 :(得分:1)

E的对象包含CD子对象,每个子对象都包含一个B子对象。由于没有关于B的虚拟继承,CD 中的每一个都包含自己的B 副本。

d.set_c()然后引用B中包含的D并更新,c.get_c()引用B中包含的C,它独立于D中的那个,因此没有改变。

对于类A及其成员n,没有这样的问题,因为使用了虚拟继承。这样可以确保在类E的最终对象中,每个人都只使用一个子对象A,无论通过哪个“路径”进行访问。

答案 2 :(得分:0)

更改

, public B

, virtual public B

获取输出a2b3

在您的示例中,E实例包含用于分隔B个实例。