c ++中的递归组合

时间:2016-04-14 06:49:29

标签: c++ oop inheritance design-patterns polymorphism

在我的C ++项目中,我经常遇到以下情况:我有一个类A,它有一个指向另一个类X的接口的指针。 该类A已扩展为处理X的子类型。而这种情况又重演了。

请注意,在每个层中,接口都会更改(添加了新的对象方法,而其他一些方法会被重载),因此在A的每个子类中,指向X的指针都会转换为子类X

+----------+                   +----------+
|          |    A has X        |          |
|   A      +------------------->    X     |
+-----+----+                   +-----+----+
      |                              |
      |                              |
      |                              |
+-----+----+                   +-----+----+
|          |                   |          |
|    B     +------------------->     Y    |
+-----+----+                   +-----+----+
      |                              |
+-----+----+                   +-----+----+
|          |                   |          |
|   C      +------------------->    Z     |
+----------+                   +----------+

我想知道是否有任何处理这种情况的模式,或者它本质上是一个糟糕的设计?

编辑,请考虑以下结构:

+----------+          +----------+                   +----------+
|          |          |          |    A has X        |          |
|    M     <----------+   A      +------------------->    X     |
+-----+----+          +-----+----+                   +-----+----+
      |                     |                              |
      |                     |                              |
      |                     |                              |
+-----+----+          +-----+----+                   +-----+----+
|          |          |          |                   |          |
|     N    <----------+    B     +------------------->     Y    |
+-----+----+          +-----+----+                   +-----+----+ 
      |                     |                              |
+-----+----+          +-----+----+                   +-----+----+
|          |          |          |                   |          |
|    L     <----------+   C      +------------------->    Z     |
+----------+          +----------+                   +----------+

这实际上是应用程序的外观。每个级别代表我们多层框架中的一个层。

2 个答案:

答案 0 :(得分:1)

考虑这个实现:

struct X {};    
struct Y: X {};
struct Z: X {};

class A
{
    // todo: add public interface
protected:
    std::unique_ptr<X> x_;
};

template<typename T>
class AImpl: public A
{
protected:
    T* get() { return dynamic_cast<T*>(x_.get()); }
};

class B: public AImpl<Y>
{
public:
    // todo: add public interface
    using AImpl<Y>::get; // implement rest of B in terms of this
};

class C: public AImpl<Z>
{
public:
    // todo: add public interface
    using AImpl<Z>::get; // implement rest of C in terms of this
};

编辑(因为C需要从B继承)

考虑按如下方式定义B和C:

template<typename T>
class BImpl: public AImpl<T>
{
public:
    // todo: add public interface
    using AImpl<T>::get; // implement rest of B in terms of this
};

// this is a new thing (see my explanation on this, below)
using B = BImpl<Y>;

class C: public BImpl<Z>
{
public:
    // todo: add public interface
    using AImpl<Z>::get; // implement rest of C in terms of this
};

虽然这样实现B有一个问题:让你的课做不止一件事的设计很糟糕。在这种情况下,B必须既是基类(对于C)又是具体类型。

我创建了一个B实现类作为基础。然后,定义B可以是类型别名(我上面的使用语句),也可以是具体类型专门化:

class B: public BImpl<Y> {};

答案 1 :(得分:-2)

你在这里被称为&#34;钻石问题&#34; (参见Wikipedia)并且可以使用虚拟继承来解决(参见this article)。

class InterfaceA
{};

class TypeA: public virtual InterfaceA
{};

class InterfaceB: public virtual InterfaceA
{};

class TypeB: public TypeA, public InterfaceB
{};

不要使用reinterpret_cast从TypeB转换为InterfaceA(虚拟继承具有与直接继承不同的内存布局)