代码之家  ›  专栏  ›  技术社区  ›  philsquared

实时推导

  •  8
  • philsquared  · 技术社区  · 14 年前

    有一个不太常见的C++习语,过去我已经用过好几次了。我只是不记得它是否有一个常用的名字来描述它。

    它与 mixins , CRTP type-erasure 但不是特别的。

    当您希望向类中添加一些实现,但不希望将其放置时,会发现问题。 在里面 类或其派生的任何类。这样做的一个原因可能是类可能是继承层次结构的一部分,在继承层次结构中,实现只应出现一次。

    暂时撇开诸如一个层次结构是否应该有具体的非叶类,或者在某些情况下虚拟继承是否是一个选项这样的问题不谈,我知道有一个解决方案可以在从模板参数派生的模板类中提供实现。这样,您就可以在创建实例时使用模板,但只能通过指针或引用对象的一个基来使用该对象(这就是类型擦除,从松散的意义上说,就是在这种情况下出现的)。

    例如,您有一个侵入式引用计数。所有类都从引用计数接口派生,但您只希望引用计数本身以及引用计数方法的实现出现一次,因此您将它们放入派生模板中-让我们调用它 ImplementsRC<T> .现在可以创建这样的实例:

    ConcreteClass* concrete = new ImplementsRC<ConcreteClass>();
    

    我正在处理一些事情,比如转发由多个模板化重载组成的构造函数等。

    所以,希望我已经弄清楚了这个成语是什么。现在回到我的问题上——这个成语是否有一个公认的,或者至少是通常使用的名字?

    9 回复  |  直到 13 年前
        1
  •  1
  •   jonnii    14 年前

    我肯定会认为这是混血儿,布鲁斯·埃克尔也是。( http://www.artima.com/weblogs/viewpost.jsp?thread=132988 )

    在我看来,使其成为混合体的原因之一是它仍然是单一继承,这与使用mi实现类似的东西不同。

        2
  •  3
  •   Matthieu M.    14 年前

    这是一个有趣的想法。然而,我不打算在这里给你一个已经建立的模式的名称,相反,我要解释(某种程度上)为什么我认为它已经没有一个了。

    它是做什么的?

    这是避免可怕的钻石遗产的一个非常好的方法。

    由于方法的目的显然有些混淆,让我详细说明为什么我认为这是它的目的:

    class RefCounted
    {
      virtual void addReference() = 0;
      virtual void removeReference() = 0;
    };
    
    class B: public RefCounted {};
    class C: public RefCounted {};
    
    class Diamond: public B, public C {};
    

    现在,我们遇到了一个问题。如果我们把 RefCounted 在这个类中,它变成了一个基类而不是一个接口,因此我们必须使用虚拟继承,否则数据成员将被复制(同时存在于B和C中)。

    因此,我们的想法是将实现推迟到最后一刻。

    优势:

    • 不需要再去猜测b或c的用法:虚拟继承在那里是不必要的。
    • 如果忘记添加实现,编译器会很好地提醒您,因此无需担心这一点。

    不方便:

    • 把负担放到客户机上:你最好有一个工厂来创建你的对象,特别是因为一个对象可以实现各种接口!!!!注意,这可以通过模板元编程(或多或少)实现自动化,也可以由类作者简单地提供。

    提供的示例:

    // d.h
    class D: public B, public C
    {
    public:
      typedef ImplementRC<D> concrete_type;
      static concrete_type Build(int, int); // Named Constructor idiom
    
    private:
      D(int,int);
    }; // class D
    
    // main.cpp
    D::concrete_type myD = D::Build(1,2);
    

    那叫什么名字?

    我想不出任何与此完全匹配的东西。桥和装饰一直提到,但这是非常特殊的,确实不是面向对象(例如,它不会发生在爪哇,因为你没有多继承),所以我怀疑这个词将在GoF的书中找到。

    而且,它不是真正的CRTP,因为CRTP中有一种循环(基础意识到它的派生类),而这种循环在这里没有发生>我们确实是严格线性的!

    然后,它肯定不是PIMPL习惯用法,它建议在使用模板进行实现时,将实现隐藏在远离客户机的地方,而只是将它抛到自己的脸上!(模板可以使用PIMPL作为内部细节)

    我谦虚地建议 吉蒂 对于 及时实施 它以某种方式模仿了标题,但更接近我认为的观点,这里的派生只是一个工具,而不是一个目标。

    不管怎样,这个主意很有趣。

        3
  •  1
  •   Andreas Brinck    14 年前

    我不确定这是否有名字,因为gf建议它看起来有点像桥型。这几乎就像是将功能挂接到基类上。

    我建议给这个取个新名字 pimp 成语。当你给你的基础阶级拉皮条时;)

        4
  •  1
  •   Loki Astari    14 年前

    你在找 Decorator pattern ?

    基本上,decorator是一个包含另一个对象并扩展某些方法功能的对象。然后,方法调用被转发到封闭的方法。

        5
  •  1
  •   Itay Maman    14 年前

    这是一个混音

        6
  •  1
  •   Chris Oldwood    14 年前

    查看您的引用计数示例,您可能会很高兴地看到ccombject<>,它是ATL包含的用于提供IUnknown实现的少数模板类之一。它还使用策略类来改变行为。很自然地,信噪比尝试谷歌 关于 cMobject非常低,因为它无处不在。这个msdn文章可能会给你更多的“关键字”来帮助任何搜索。

    http://msdn.microsoft.com/en-us/library/c43h4867(VS.80).aspx

    [注:只是说清楚-我不是建议他 使用 cCombject,我建议它是同一概念的另一个流行例子,因此可能在模式书或文章中被引用]

        7
  •  0
  •   Klaim    14 年前

    看起来像 Pimpl idiom 是吗?可能是以一种不寻常的方式使用。

        8
  •  0
  •   Ashish    14 年前

    我不确定,但它是“空成员C++优化”吗?

    这种行为是用 类模板 私人继承 .

    这在杂志上一篇名为 C++中的“计数对象” 作者:Scott Meyer。

        9
  •  0
  •   philsquared    13 年前

    回答我自己的问题。第一个疯狂的迹象?-不,在这之前有几个迹象;-)

    不管怎么说,从我最初发表文章到现在已经很久了,不管怎样,我或多或少是一个不同的人。

    我发现我已经确定了名字, 混频 . 我发现这非常适合,可以被认为是一个混合的精致,而不是被排除在更普遍的概念。

    我最近一直在使用它们,所以我想我会回来更新这个线程。