c++ - 多重继承+虚函数困惑

标签 c++ multiple-inheritance virtual-functions diamond-problem

我有一个像这样的菱形多重继承场景:

    A
  /   \
 B     C
  \   /
    D

共同的父节点 A 定义了一个虚函数 fn()。
B和C都可以定义fn()吗?
如果是,那么下一个问题是 - D 可以无歧义地访问 B 和 C 的 fn() 吗?我假设这有一些语法..
D 是否有可能在不明确知道 B 和 C 是谁的情况下这样做? B 和 C 可以被其他一些类替换,我希望 D 中的代码是通用的。

我想要做的是让 D 以某种方式枚举它在其祖先中拥有的所有 fn() 实例。这是否可能以其他方式表示虚函数?

最佳答案

除非您在 D 中再次覆盖 fn,否则这是不可能的。因为在 D 对象中没有最终覆盖器:CB 都覆盖了 A::fn。您有多种选择:

  • 删除 C::fnB::fn。然后,仍然覆盖 A::fn 的那个拥有最终的覆盖器。
  • 在 D 中放置一个最终覆盖器。然后,该覆盖器覆盖 A::fn 以及 CB 中的 fn

例如以下导致编译时错误:

#include <iostream>

class A {
public:
    virtual void fn() { }
};

class B : public virtual A {
public:
    virtual void fn() { }
};

class C : public virtual A {
public:
    virtual void fn() { }
};

// does not override fn!!
class D : public B, public C {
public:
    virtual void doit() {
        B::fn();
        C::fn();
    }
};

int main(int argc, char **argv) {
  D d;
  d.doit();
  return 0;
}

但是,您可以从 C 和 B 中的 A 派生非虚拟,但是您不再有菱形继承(钻石问题)。也就是说,A 中的每个数据成员在 B 和 C 中出现两次,因为在 D 对象中有两个 A 基类子对象。我建议您重新考虑该设计。尝试消除需要虚拟继承的双重对象。它经常导致这种冲突的情况。

与此非常相似的情况是您想要覆盖特定函数。想象一下,你在 B 和 C 中有一个同名的虚函数(现在没有共同的基 A)。在 D 中,您希望覆盖每个函数,但为每个函数赋予不同的行为。根据您是使用 B 指针还是 C 指针调用函数,您会有不同的行为。 Multiple Inheritance Part III Herb Sutter 的作者描述了一个很好的方法。它可能会帮助您决定您的设计。

关于c++ - 多重继承+虚函数困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/616380/

相关文章:

java - 如何避免由于无法使用多重继承而导致重复代码。 hibernate

c++ - CUDA 内核可以是虚函数吗?

C++虚函数。vtable问题

C++智能指针

c++ - 是否可以将类型映射到整数?

c++ - 通过基初始化派生类

c# - 继承泛型构造函数 C#

c++ - 如何根据不同的参数定义相同的宏函数

c++ - basic_regex 使用 char32_t 抛出 bad_cast

c++ - 为什么我在这个函数中会出现越界异常?