【问题标题】:Possibility to mix composite pattern and curiously recurring template pattern混合复合模式和奇怪重复的模板模式的可能性
【发布时间】:2012-12-13 20:26:10
【问题描述】:

我有一个复合模式实现,用于 GUI 组件:

class CObject {
private:

  CObject * m_pParent;  
  CObjectContainer * m_pChildren;

  void private_foo() {
    this->foo();
    //Calls private_foo for each child in container.
    m_pChildren->foo();
  }

public:
  virtual void foo() {
    //empty for base class
  }

  virtual CObject * duplicate() {
    //Do duplication code
    return new CObject(*this);
  }

  virtual CObject * detach() {
    //Remove this object (along with it's children)
    //from current tree.
    m_pParent->RemoveChild(this);
    m_pParent = nullptr;
    return this;
  }
}

class CSpecificObject : public CObject {
public:
  virtual void foo() {
    //Specific code for this class
  }

  virtual CSpecificObject * duplicate() {
    //Overload, but the code only calls diferent constructor
    return new CSpecificObject(*this);
  }

  virtual CSpecificObject * detach() {
    //Note the code is identical.
    m_pParent->RemoveChild(this);
    m_pParent = nullptr;
    return this;
  }
}

不幸的是,继承类的数量迅速增加,重复的代码(在给定的示例中只有 detach() 方法)让我头疼。

有没有办法干净地实现 detach() 方法,保持返回类型与调用它的对象相同?

我在考虑 CRTP,但我想不出一种方法来保持动态多态性和编译时多态性:

template <Child>
class CObject {
private:
  ...
  Child * detach() {
    m_pParent->RemoveChild(this);
    m_pParent = nullptr;
    return static_cast<Child*>(this);
  }
  ...
}

//Array of CObject* pointers is no longer possible.

【问题讨论】:

    标签: c++ templates design-patterns composite crtp


    【解决方案1】:

    您可以添加一层抽象:

    class CObjectBase
    {
        public:
            // Other methods...
            virtual CObjectBase* detach() = 0;
            virtual CObjectBase* duplicate() const = 0;
    };
    
    template <typename Child>
    class CObject : public CObjectBase
    {
        public:
            // ...
            Child* duplicate() const
            {
                return new Child(*static_cast<Child*>(this));
            }
    
            Child* detach()
            {
                m_pParent->RemoveChild(this);
                m_pParent = nullptr;
                return static_cast<Child*>(this); // Cast needed here (inherent to CRTP)
            }
            std::vector<CObjectBase*> children; // Array possible now
            // ...
    };
    
    class MyObject : public CObject<MyObject>
    {
        // ...
    };
    

    在自然语言中:所有对象的接口 (CObjectBase) 都有其后代 (CObject&lt;Child&gt;) 的部分实现,它只需要继承这个部分实现,从而减少复制代码的数量。

    【讨论】:

      【解决方案2】:

      我在考虑 CRTP,但我想不出一种方法来保持动态多态性和编译时多态性

      您可以通过使用 CRTP 样式基类为某些接口提供默认虚拟实现来混合它们。

      因此,您可以聚合 CRTP 基本实现(可能配置有额外的“策略”模板参数),并且仍然能够覆盖继承类中的特定行为。

      微软的ATL library 经常使用这个。 我也在我的STTCL state machine library 中使用了这种技术。

      【讨论】:

        【解决方案3】:

        仅从 sn-p 就不清楚为什么需要 detach() 来返回指向已传递类型的指针。

        要利用 detach() 返回交付的类型,无论如何都需要使用对交付类型的引用来调用它。像这样:

        CSpecificObject* specific_object = new SpecificObject();
        // ...
        specific_object->detach()->method_declared_in_specific_object();
        

        但这可以替换为即使分离无效的等效项:

        specific_object->detach();
        specific_object->method_declared_in_specific_object();
        

        如果你有对基类型的引用,你就不能利用detach()返回类型:

        CObject* specific_object = new SpecificObject();
        //...
        // !!! Won't compile:
        specific_object->detach()->method_declared_in_specific_object(); 
        

        因此,不清楚您尝试实施的方法有哪些优势。

        另一方面,duplicate() 方法很臭。当交付的类不覆盖它时它会中断,而是使用父类的默认实现。这可能表明高层设计有问题。

        【讨论】:

        • detach() 方法的使用方式很丑:CObject * tree_of_stuff; -- 完整的对象树 CSpecificObject * specific_object = tree_of_stuff-&gt;Child&lt;CSpecificObject&gt;("StringId")-&gt;detach(); 这里Child&lt;&gt;() 方法沿着树进行搜索并将对象转换为指定的模板范围。如果detach() 返回voidCObject *,则此语法不可用。
        • duplicate() 方法是一定的错误来源,这也是我使用 CRTP 扩展当前模式的原因之一。在我看来,依赖复制构造函数比承诺每个人都会实现duplicate() 方法更安全。
        猜你喜欢
        • 2012-04-30
        • 2022-01-01
        • 2013-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多