说我有4节课:
class I { public: virtual void X() = 0; };
class A : public virtual I { public: virtual void X() { } };
class B : public I { };
class C : public A, public B { };
I
,B
和C
是抽象的,而A
则不是。{1}}。如果我只是将virtual
添加到I
B
的继承,那么A::X()
会在I::X()
中解析C
。
但是,我无法更改B
的来源。
我的问题:我是否可以A::X()
解析I::X
C
而无法更改B
?我已尝试将A
和B
声明为C
虚拟无效。我试图没有冗余代码(例如,有C声明X(){A :: X();})。任何整洁的黑客?
此外 - 有一些非常类似的问题,但我找不到任何关于使用virtual
继承的讨论。如果我错过了,请指点我。
答案 0 :(得分:3)
你的问题在于vtables。在您当前的代码中,您有两个 - 一个在A
的{{1}}中,另一个在I
的{{1}}中。只要B
实际上只继承I
,您就可以使用常规继承并节省开销。如果两者都是虚拟继承A
,那么I
中只有一个I
个实例,因此只有一个vtable,而I
确实可以覆盖纯C
A::X
}。
鉴于您无法更改I::X
,您唯一可以处理这两个vtable的地方是B
。在我看来,你要提到的方法是 - 只需要C
将呼叫转发给C::X
。那里没有代码重复,它使A::X
非抽象:
C
至于虚拟继承,肯定有have been some here。但是欢迎你问...
答案 1 :(得分:2)
这非常好:When virtual inheritance IS a good design?
这里的问题是在C中你有两个接口I.这就是A :: x()满足的原因 它的接口我 - 但它不能使B类中的抽象接口不能生成。 对于C来说,只有一个I接口的唯一方法是将B改为从虚拟中导出 - 这样来自A和B的I接口将合并为C中的一个。你不能改变B - 所以唯一方法是添加您要避免的冗余代码。我的意思是定义C :: X()。
答案 2 :(得分:1)
我能想到的唯一方法是将B*
(或智能变体)组合成C
而不是继承它,并转发适当的方法。在维护继承时不能这样做,因为编译器不知道要跟随哪个I
的继承链。