钻石继承和纯虚函数 [英] Diamond inheritance and pure virtual functions

查看:143
本文介绍了钻石继承和纯虚函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下标准的钻石继承。类A定义了纯虚函数fx,类B定义了fx的实现,类C和D对fx没有任何作用。当试图在类D的实例上调用fx时,虽然只有一个fx实现,但会得到'模糊函数调用'错误。这可以通过以虚拟方式从A继承的B和C来解决。这是一个正确的问题解决方案吗?虚拟继承如何处理虚拟函数表的合并?

A ---> B ---> D



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

解决方案

...注意,Herb Sutter写道关于多重继承的3篇优秀文章(1)here (2)here and (3)在这里。他在本周的这里写了一大堆有用的文章。强烈建议...



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

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

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

嗯,D是抽象的,因为有两个 A D类型的对象中的子对象:通过B的格子由 B 具体化的子对象,以及通过<$ ç$ C> C 。我认为你有一个指向 D 的指针并尝试调用 F 。是的,会产生歧义,因为编译器会在两个单独的格子中找到两个函数 F

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

看起来像这样:

  F()F()
AA
| |
F()BC
\ /
D

您可以通过从A中派生出来正式地修复这种情况:

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

然后你有这种情况,称为钻石继承:

  F()
A
/ \
F()BC
\ /
D

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

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

Imagine a standard diamond inheritance. Class A defines pure virtual function fx, class B defines implementation for fx, classes C and D do nothing with fx. When trying to call fx on instance of class D you'll get 'ambiguous function call' error although there is only one implementation of fx. This can be solved by B and C inheriting from A in virtual manner. Is it a correct solution for the problem? How exactly does virtual inheritance handle merging of virtual function tables?

A--->B--->D

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

解决方案

... Note, Herb Sutter wrote 3 excellent articles about multiple inheritance (1) here, (2) here and (3) here . He wrote a whole other bunch of useful articles in guru-of-the-week here. Highly recommended ...

First, i'm not sure that i get your hierarchy right. I take it it is like this:

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

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

Well, D is abstract, because there are two A subobjects in an object of type D: One that is made concrete by B through the lattice of B, and one that is still abstract in the lattice going through C. I take it you have a pointer to D and try to call F. Yes, an ambiguity arises, because the compiler finds two functions F in two separate lattices:

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

Looking like this:

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

You can fix that situation formally by deriving from A virtually:

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

You then have this situation, called diamond inheritance:

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

And doing the lookup, it finds that there is B::F overriding A::F. Although A::F can still be reached through D::C::A, that is not an ambiguity anymore, because A was inherited virtual.

Whether this is the correct solution in your particular problem - that's of course not certain. There are most often better ways than deriving virtual from a class. To your question about merging of virtual function tables - that's completely depending on the implementation. GCC, as far as i know, will keep a pointer to the one A instance in the virtual table of D, if we derive virtual.

这篇关于钻石继承和纯虚函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆