假设我有一个作为单根树的大型类层次结构,根为class A
,因此它的每个子代都有自己的void f(...)
和void g(...)
实现,具有不同的参数列表。
我有另一个类class X: public A
,它在一些方法中只使用基类f(...)
和g(...)
。现在我想将X
中的方法扩展到A
的所有子类型:假设A
的子类型是B
,新类是class BX
。要求是:
- (实现(
class BX
应该使用class B
中的f(...)
和g(...)
,以及class X
中的所有方法 - (接口(
class BX
应与class A
的接口保持一致
我提出的解决方案是使用template<typename B> class BX: public B
来避免1中的钻石问题。
有更好的方法来实现我想要的吗?
根据我的经验,如果你只继承接口(即仅虚拟接口(并使用组合和委派来共享实现,那么继承的很多问题就会消失,然而,你在这里使用的奇怪的重复模板模式或CRTP是解决这个问题的另一种常见方法。
template<class D>
struct X {
A* self(){ return static_cast<D*>(this); }
A const* self() const{ return static_cast<D*>(this); }
void foo(){
self()->f( 1, 2, 3 );
}
};
struct XA: A, X<XA> {};
struct XB: B, X<XB> {};
在X<XB>
,即XB
的实现中,您只能访问A
。
如果希望用户只看到A
,则只将XB
公开为A
。
请注意,这可能非常无用,因为访问XB
/X<XB>
中的任何更改都需要知道您的对象不是A
,因为X<XB>
不会修改A
接口中的任何内容。