多继承和数据成员

use*_*129 5 c++ oop multiple-inheritance

我从来没有使用多重继承,偶然发现了一个我从未遇到过的设计问题.

class A {
     //..methods..
}

class B : public A {
    int b;
    //...methods..
}

class C : public A {
    int c1,c2;
}

class D : public B,public C {
}
Run Code Online (Sandbox Code Playgroud)

这是经典的钻石.事实是,这C真的只是一个A额外的两个整数.而D实际上只是一个聚集BC,但我觉得多重继承并不是用来做这样的事情.或者可能还有其他最佳做法可以做到这一点.

我试图实现多重继承的原因是我想编写一个类似的函数void func(A*)并将其传递给一个AD类指针.我的天真尝试是做一个简单的演员:

void func(A* a) { // <-- I call this with a A or D pointer
   // ..do something with A members..

    if(is_the_case) { // <-- Im sure the passed "a" pointer is actually a *D
        D* d = (D*)a;
       // ..do something with the extra 2 ints provided by the C class..
    } 
}
Run Code Online (Sandbox Code Playgroud)

不起作用..编译很好,但是if(is_the_case)执行时我有一个非常奇怪的行为,清除了2个额外的int,c1并且c2也清除了b(继承B).

我重新考虑钻石问题,但这里只有一个B(和2个A)层次结构,所以我不明白为什么要b清除它.只是为了尝试,我使用了公共虚拟BC声明.现在每个演员都是编译错误,除非我使用dynamic_cast..

有人能说清楚幕后发生了什么吗?考虑到还有其他课程,最好的做法是什么:

class E : public A {
    int e;
    //..methods..
}

class F : public E,public C {
}
Run Code Online (Sandbox Code Playgroud)

也就是说,其他类只是一个类的聚合,派生自A+继承的两个额外的int,C并且可以传递给一个需要的函数*A

谢谢,尽我所能尽可能清楚..

Pup*_*ppy 4

您的代码之所以有效,是因为您使用了 C 风格的强制转换,它可以是 a reinterpret_cast,并且据我所知,您可以reinterpret_cast在任意两个指针类型之间进行转换,即使它没有意义。dynamic_cast从多重继承的基类转换为更派生的类时,必须使用 a 。Astatic_cast会产生编译时错误。事实上,dynamic_cast它同时完成两项工作。

void func(A* a) { // <-- I call this with a A or D pointer
   // ..do something with A members..

    if(D* d = dynamic_cast<D*>(a)) { // a definitely points to a D
        // and we got a guaranteed good pointer too
    } 
}
Run Code Online (Sandbox Code Playgroud)

这是一个很好的例子,说明了为什么应该避免 C 风格的强制转换。