我有一个像这样的钻石多重继承场景:
A / \ B C \ / D
公共父A定义了虚函数fn().
B和C都可以定义fn()
吗?
如果是,那么下一个问题是 - D可以访问B和C的fn()而不消除歧义吗?我假设有一些语法...
而D是否有可能在不知道谁是B和C的情况下做到这一点?B和C可以替换为其他类,我希望D中的代码是通用的.
我想要做的是让D以某种方式枚举它在其祖先中具有的fn()的所有实例.这是否可能在某些其他方面表示虚函数?
除非你fn
再次覆盖D
,否则不可能.因为D对象中没有最终覆盖:Both C
和B
覆盖A::fn
.你有几个选择:
掉落C::fn
或B::fn
.然后,仍然覆盖的那个A::fn
具有最终的覆盖.
放在D.最终置换器之后,一个覆盖A::fn
藏汉为fn
中C
和B
.
例如,以下结果导致编译时错误:
#includeclass 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指针调用该函数,您具有不同的行为.Herb Sutter的多重继承第三部分描述了一种很好的方法.它可能会帮助您决定您的设计.