什么是C++混合风格(Mixin-Style)?

38

我刚接触到这个关键词 C++ Mixin-Style,有人知道这是什么吗?

这篇帖子中,它被回答为一种设计模式。它是否与此文档中描述的相同的设计模式?


2
你读过 http://www.cs.umass.edu/~yannis/practical-fmtd.pdf 吗? - Seth Carnegie
是的,我知道这是什么 :) 你提到了简短而好的描述。另一个好的描述可以在Andrei Alexandrescu的《现代C++设计》中找到。你能详细说明一下你的问题吗? - Andriy Tylychko
5个回答

24

Mixin是来自Lisp的一个概念。下面引用自Dr. Dobbs中的很好的解释:

Mixin是类的一个片段,它旨在与其他类或mixin组合使用。
[...]
常规独立类(例如Person)和mixin的区别在于,mixin对某些小的功能切片进行建模(例如打印或显示),并且不适用于独立使用。相反,它被设计为与需要该功能的其他类(例如Person)组合使用。

因此,mixin的目的是允许类似于多重继承的东西,而没有通常伴随多重继承的所有问题。

然而,这可能有点令人困惑,因为C++并不原生支持mixin;为了在C++中实现mixin,您必须使用多重继承!实际上,这意味着您仍然使用多重继承,但人为地限制了您允许自己使用它的范围。

请参阅上面的文章以获取实际的mixin实现。


16
如果我没记错的话,C++中至少有两种方法来创建mixin。这是来自一个非常古老的(1995年)教程,我看过它(但现在已经几乎从互联网上消失了)。
首先,
class MixinBase {
public :
    void f() {};
};

template<class T>
class Mixin : public T {
public:
    void f() {
        T::f();
        T::f();
    }
};

template<class T>
class Mixin2 : public T {
public :
    void g() {
        T::f();
        T::f();
    }
};

int main() {
    Mixin2<Mixin<MixinBase>> mix;
    mix.g();
}

或者另一种方法是使用虚拟继承和兄弟调用:

class Base {
public :
    virtual void f() = 0;
};

class D1 : public virtual Base {
public :
    void g() {
        f();
    }
};

class D2 : public virtual Base {
public :
    void f() {
    }
};

class D : public D1, public D2 {
};

int main() {
    D d;
    d.g();
}

现在这两个版本都实现了mixins,因为Mixin和Mixin2是独立的类,但它们仍然可以通信。您可以使用此类模块创建软件,然后稍后将这些模块绑定到一个大型软件中。虚拟继承中D1和D2之间发生相同的情况很重要的一点是,在mixin设计中,不同的模块存在于同一个C++对象中(顺便提一下,CRTP是一种不同的技术)。

你的第一个mixin案例不是与traits相同(或类似)吗? - dragonxlwang
第一个例子非常有用,因为您不必更改任何类以扩展其行为。但我仍然困惑于客户端如何从mixin中受益:客户端是否可以要求您将Mixin2 const&传递给函数?客户端只能是函数模板,其中(mixin)参数作为模板参数传递吗?您能否提供一些示例,说明如何利用Mixin2<Mixin1<T>>? - Grim Fandango
我也感谢您提到“CRTP是一种不同的技术”。 - Grim Fandango

8

Mixin是一个类(或其他代码组)的名称,旨在通过直接包含在另一段代码中来实现重用。可以将其视为没有子类型多态性的继承。CRTP是在C ++中近似Mixin的一种方式。


5
通常所谓的mixins是指一些小类(通常基于模板或CRTP实现),你可以从这些类中继承出“混入”一些功能; 通常使用多重继承和策略设计(也可以参考Alexandrescu的《Modern C ++ Design》)。

我不同意。 "Mixins" 的目的是通过语言设计/限制(如Scala、Ruby和Squeak)或通过C++中的CRTP来避免多重继承 - 解决共享实现的90%问题,而只有10%的复杂性(MI)。顺便说一下,这些数字是我编造的 :-) - user166390
4
@pst,你知道吗?84%的统计数字是即兴捏造出来的。每次我见到一个mixin,无论是否使用CRTP技术,它都会使用多重继承。我认为这就是“混合”(mix)的意义所在,它是用来与其他基类混合使用的。 - Mark Ransom
2
根据Jim Coplien在他的《高级C++》一书中所述,mix-ins是Flavors语言中存在的一种动态多重继承形式,您可以在运行时组合多个基类以创建特定的派生类。 - Nicola Musatti
@mixin:mixin 的独特特点在于它旨在用于继承,而不是单独实例化。避免由于继承链导致的 MI 是设计 mixin 的一种方式,但它们的关键点仍然是重用代码,而不是防止 MI。 - PlasmaHH

3

1
Mixins 是 CRTP 的设计反转。两者具有区别,而 Mixins 并没有使用 CRTP 实现。 - user3814483

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接