【问题标题】:Multiple Inheritance :Java vs C++多重继承:Java vs C++
【发布时间】:2016-09-08 21:16:35
【问题描述】:

最近在阅读《编程语言与实践》一书中的一些文章后,提到Java中的多接口继承与C++中的多类继承没有同样的问题。

但我不明白为什么会这样。 java如何在存在C++实现错误的情况下使用多接口继承??

有没有办法在 C++ 中替换多重继承以避免实现问题??

为了更具体的最后一条语句,可以说我们有:

class A {...};
class B : public A {...};
class C : public A {...};
class D : public B, public C {...};

然后类 D 继承类 B,C,它们都继承类 A。因此,如果 A 有一个字段变量,那么 B,C 将具有相同的变量名,那么 D 将具有什么变量(从 B 或 C 继承)。为了避免这种情况,我们是否可以编写上面的代码而不使用多重继承但结果相似?

这个问题不是重复的,因为它没有关注示例中的最终继承是什么,而是要了解 Java-C++ 多重继承之间的区别(参见上面的第一个问题)以及是否有办法建议克服一些多重继承问题(如上)。

【问题讨论】:

标签: java c++ inheritance


【解决方案1】:

Java(与 C++ 不同)不允许 statemultiple inheritance,因此不会受到 diamond problem 的影响。

它允许通过接口实现type的多重继承(一个类可以实现多个接口)。

从 Java 8 开始,还通过接口中的default 方法实现了行为的多重继承。

【讨论】:

  • 这只是部分回答了这个问题。如果可能的话,OP 要求为多重继承提供 alternatives
【解决方案2】:

但我不明白为什么会这样。 java如何在存在C++实现错误的情况下使用多接口继承???

这是可能的,因为Java 不允许多重继承,而只能从多个接口 多重实现

实现不同于继承

多重继承的一般问题是(简而言之t)两个类可能会定义不同的方式来做同样的事情,并且子类无法选择选择哪一个。

由于java中的interface可以only声明方法的签名而不实现它们,所以如果派生多个接口就不存在这个问题。

总之,为了避免这个问题,Java直接禁止多重继承,只允许接口的多重实现。


有没有办法在c++中替换多重继承以避免实现问题???

我能给你的第一个建议是避免设计如此复杂。

无论如何,您在问题中暴露的问题很常见,称为diamond problem

C++ 提供了一个解决方案,以使用virtual inheritance 来解决该问题。

让一个继承图:

    A
 /     \
B       C
 \     /
    D

这就是问题所在:

默认情况下,C++ 分别遵循每个继承路径,因此 D 对象实际上将包含两个单独的 A 对象,并且必须正确限定 A 成员的使用。

这是关于virtual继承的简要说明:

如果从AB 的继承以及从AC 的继承都标记为“虚拟”(例如,“class B : virtual public A”),C++ 会特别注意只创建一个A 对象A 的成员的使用工作正常。如果虚拟继承和非虚拟继承混合使用,则到 A 的每个非虚拟继承路径都有一个虚拟 A 和一个非虚拟 A。

简而言之,使用virtual 继承可以防止部分类A 在类D 中重复。

【讨论】:

    【解决方案3】:

    为了避免这种情况,我们是否可以编写上面的代码而不使用多重继承但结果相似?

    它遵循一个最小的工作示例:

    struct A {};
    struct B {};
    struct C {};
    
    struct D {
        operator A&() { return a; }
        operator B&() { return b; }
        operator C&() { return c; }
    
    private:
        A a;
        B b;
        C c;
    };
    
    void f(const B &b) {}
    
    int main() {
        D d;
        f(d);
    }
    

    如果您不想创建显式层次结构,但仍想使用 D 的实例,其中需要引用 B,则上述解决方案效果很好。
    如您所见,它基于组合而不是继承。
    当然,它有一些限制,例如,您不能将指向 D 的指针转换为指向 B 的指针。

    它是否符合您的要求主要取决于真正的问题,所以我不能说。
    无论如何,这是一个类似于inner class idiom 的可行解决方案,如果您有兴趣了解更多详细信息。

    【讨论】:

    • 感谢您的替代实施!
    【解决方案4】:

    Java 中的“多重继承”并不是真正的多重继承。由于 Java 只能通过使用接口来创建菱形问题。

    接口只是对子类中已实现方法的引用,因为接口不能实现方法。

    所以子类不能有不同实现的父类。从哪个接口继承该方法并不重要,因为不存在任何实现。

    编辑:哦,我忘了Java是如何通过引入default方法来破坏接口背后的原理的……

    【讨论】:

    • 非常感谢您的回答!!
    • Java 无法创建菱形问题。给定方法只有一个实现。
    • 实际上,使用默认方法可以产生问题:stackoverflow.com/questions/16764791/… 默认方法不好的原因有多种,这甚至不是最糟糕的。我认为意图很好,实施很糟糕。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    • 2017-03-31
    • 2012-05-14
    • 2013-08-28
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多