c++ - 菱形继承(钻石问题)和纯虚函数

标签 c++ function inheritance virtual

想象一下标准的菱形继承(钻石问题)。 A 类定义纯虚函数 fx,B 类定义 fx 的实现,C 类和 D 类对 fx 不做任何处理。当尝试在类 D 的实例上调用 fx 时,尽管只有一个 fx 实现,但您会收到“模糊函数调用”错误。这可以通过B和C以虚拟的方式继承A来解决。它是问题的正确解决方案吗?虚继承究竟是如何处理虚函数表合并的?

A--->B--->D

\--->C------^

最佳答案

... 注意,Herb Sutter 写了 3 篇关于多重继承的优秀文章 (1) here , (2) here(3) here .他在本周大师中写了一大堆有用的文章 here .强烈推荐...

首先,我不确定我是否正确理解了您的层次结构。我认为它是这样的:

struct A {
    virtual void F() = 0;
};

struct B : A { void F() { } };
struct C : A { };
struct D : B, C { };

嗯,D 是抽象的,因为在类型 D 的对象中有两个 A 子对象:一个是 B 通过 B 的格具体化的,和一个在通过 C 的格子中仍然是抽象的。我认为您有一个指向 D 的指针并尝试调用 F。是的,出现了歧义,因为编译器在两个单独的格中找到了两个函数 F:

D -> B::F
D -> C -> A::F

看起来像这样:

    F()   F()
     A     A
     |     |
 F() B     C
      \   /
        D 

您可以通过从 A 虚拟派生来正式解决这种情况:

struct B : virtual A { void F() { } };
struct C : virtual A { };
struct D : B, C { };

然后你有这种情况,称为菱形继承:

       F()  
        A
      /   \
 F() B     C
      \   /
        D 

在进行查找时,它发现 B::F 覆盖了 A::F。虽然 A::F 仍然可以通过 D::C::A 到达,但这不再是歧义了,因为 A 是继承的虚拟的。

这是否是您的特定问题的正确解决方案 - 当然不能确定。通常有比从类派生 virtual 更好的方法。关于合并虚函数表的问题——这完全取决于实现。 GCC,据我所知,如果我们派生 virtual,将在 D 的虚拟表中保留一个指向 A 实例的指针。

关于c++ - 菱形继承(钻石问题)和纯虚函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/457609/

相关文章:

c++ - C++ 总分

c++ - 我刚刚制作的程序显然是病毒? C++

php - 在 JavaScript 函数中调用 PHP 文件更新 MYSQL 表?

php - 为什么我不能在 Javascript 函数中将字符串作为参数传递?

我可以使用 C 指针结构函数更改此 C 代码吗?

reactjs - React 中组合优于继承的好处

java - 在这种情况下,我选择组合而不是继承是正确的吗?

c++ - ubuntu 13.04 上的 Eclipse C++ 插件

c# - 基本 C# 接口(interface)问题

c++ - 在任意加长的集合中查找最大数量是行不通的