C++ C++;,菱形继承,何时何地需要实现纯虚拟?

C++ C++;,菱形继承,何时何地需要实现纯虚拟?,c++,inheritance,multiple-inheritance,pure-virtual,C++,Inheritance,Multiple Inheritance,Pure Virtual,C++:我有一个基类a和一个纯虚函数f(),然后两个类B和C实际上继承自a,还有一个类D继承自B和C(典型的菱形结构): 在以下情况下,何时何地需要实现f()=0 B和C都有纯虚函数(->抽象类必须实现继承的纯虚函数吗?) 其中只有一个(bxor C)具有纯虚函数(->另一个仍然必须实现f()?) B和C都没有自己的纯虚拟(->跳过B和C中的实现并将其“传递”给D的可能方式?) 在上述三种情况中,D需要实现f()?在哪些情况下,D可以选择实现f()?在哪些情况下,如果有的话,D不可能实现f()

C++:我有一个基类a和一个纯虚函数f(),然后两个类B和C实际上继承自a,还有一个类D继承自B和C(典型的菱形结构):

在以下情况下,何时何地需要实现f()=0

  • B和C都有纯虚函数(->抽象类必须实现继承的纯虚函数吗?)
  • 其中只有一个(bxor C)具有纯虚函数(->另一个仍然必须实现f()?)
  • B和C都没有自己的纯虚拟(->跳过B和C中的实现并将其“传递”给D的可能方式?)
  • 在上述三种情况中,D需要实现f()?在哪些情况下,D可以选择实现f()?在哪些情况下,如果有的话,D不可能实现f()
  • 对于这类问题,还有其他常见的建议吗

    谢谢

    B和C都有纯虚函数(->抽象类必须实现继承的纯虚函数吗

    是的。从抽象类继承的任何类都必须实现虚拟函数才能实例化。否则它们也将是抽象的

    其中只有一个(bxor C)具有纯虚函数(->另一个仍然必须实现f()?)

    由于
    C
    也派生自
    A
    ,因此它还应该实现
    f()

    B和C都没有自己的纯虚拟(->跳过B和C中的实现并“通过”到D的可能方式?)

    您可以这样做。但是这会阻止像这样单独实例化
    B
    C
    -

    A *obj = new B(); // Error
    A *obj = new C(); // Error
    
    在上述三种情况中,D需要实现f()?在哪些情况下,D可以选择实现f()?在哪些情况下,D不可能实现f()

    f()
    可以单独在
    D
    中实现,只要您希望它的所有父类都是抽象的

    B和C都有纯虚函数(->抽象类必须实现继承的纯虚函数吗?)

    D
    必须实现所有继承的纯虚拟函数。
    除非类实现了类的所有纯虚函数,否则它将从类本身派生为抽象类

    其中只有一个(bxor C)具有纯虚函数(->另一个仍然必须实现f()?)

    D
    必须实现通过任何层次结构中的基类继承的纯虚拟函数。如果其直接基类未定义纯虚拟函数,则该类也将成为抽象类,除非
    D
    实现继承的纯虚拟函数,否则它也将成为抽象类

    B和C都没有自己的纯虚拟(->跳过B和C中的实现并“通过”到D的可能方式?)

    D
    必须实现它通过
    A->B
    A-C
    继承的纯虚拟函数。注意,在这种情况下
    B
    C
    都是抽象类

    在上述三种情况中,D需要实现f()?在哪些情况下,D可以选择实现f()?在哪些情况下,D不可能实现f()

    D
    需要在所有上述3种条件下实现
    foo()
    ,以便能够实例化(非抽象)

    结论:

  • 一个类需要实现它从所有基类继承的所有纯虚函数,否则将使该类成为一个抽象类
  • 虚拟属性是继承的,如果一个超类声明了一个函数Virtual,那么派生类中被重写的函数也是Virtual的,并且它将虚拟属性传递给从它派生的所有类

  • 避免使用死亡钻石(Diamond of Death)!除非你真正理解其中的微妙之处。很多人试图使用虚拟继承,但这并不是实现他们的设计想要实现的最合适的方式。在某些情况下,使用虚拟继承的确是必要的,但这是一个重要的缺点truct是由该语言提供的,但更多的时候是以错误的方式使用的。因此,再次访问您的设计以验证您是否真的需要虚拟继承是有意义的

    以下可能是一本不错的读物:


  • 唯一的要求是,在“叶”级别(最派生的一个级别),每件事物都有一个实现(可能只有一个),否则,如果在访问图形的点上,在相同的“距离”上有更多的实现,就会产生歧义

    所以D必须实现所有尚未实现的东西,或者所有东西都通过不同的路径实现了不止一次(以消除歧义)。 如果某个东西——在D级——仍然没有被实现……D不能被恢复,并且实现被要求是从D派生的to和E

    -钻石是永恒的-

  • 不,抽象类(大概是
    B
    C
    )不需要实现继承的纯虚拟。但是像
    D
    这样的子类需要这样做才能实例化

  • 否,同样地,
    B
    C
    将继承纯虚方法,只需重写它即可生成最终的具体类

  • 是的,这将以两种方式之一通过实现传递到
    D
    。如果
    B
    C
    都虚拟继承,那么
    D
    将实现一次。如果它们没有虚拟继承,那么
    D
    将需要同时覆盖
    B
    C
    版本
    A *obj = new B(); // Error
    A *obj = new C(); // Error