C++ Mixin初探

文章目录

背景

在阅读源码时发现了下面的一种写法,这种写法确实
是第一次接触,一时间不理解这种写法的含义以及设计理念,于是便查找资料学习相关知识。

template<class T>
class Base : public T
{
    ......
};

最终确定这是c++实现mixin的方式,也就是Template Parameters as Base Classes,那么为什么会诞生这种较复杂的语法设计呢?其存在的意义是什么?


问题

有如下的BasePrint类用于提供打印功能:

class BasePrint
{
public :
    virtual void print();
};

实际应用中我们对这个基类进行继承扩展,实现定制不同版本的打印功能,然后自己的实际类中继承对应的打印类,选用自己需要的打印版本。

class DerivePrint1 : public BasePrint
{
public :
    // 这里为了方便就随便输出了,实际应用中比如这个print可以封装为带色彩输出或者格式化输出
    virtual void myprint() {
        cout<<"Hello World 1!"<<endl;
    }
    virtual void print() {
        myprint();
    }
};

class myClass : public DerivePrint1{
};

int main()
{
    myClass my;
    my.print();
}

那么如果此时又新增了另一种打印,我们的类中想要同时使用这两种打印呢?

class DerivePrint1 : public BasePrint
{
public :
    virtual void myprint() {
        cout<<"Hello World 1!"<<endl;
    }
    virtual void print() {
        myprint();
    }
};

class DerivePrint2 : public BasePrint
{
public :
    virtual void myprint() {
        cout<<"Hello World 2!"<<endl;
    }
    virtual void print() {
        myprint();
    }
};

class myClass:public DerivePrint1,public DerivePrint2{
};

int main()
{
    myClass my;
    // error,触发了多重继承的问题
    my.print();
}

可以看到,多重继承存在引发Diamond-Problem的风险。于是C++ 引入了虚继承,但虚继承在某些场景下也是有一定弊端的,为此C++ 作者发明了Template Parameters as Base Classes,这便是C++ 中实现mixin的方式。

回到上面的问题,以mixin的方式来实现的话:

template <typename T>
class DerivePrint1 : public T
{
public :
    void print() {
        cout<<"Hello World 1!"<<endl;
        T::print();
    }
};

template <typename T>
class DerivePrint2 : public T
{
public :
    void print() {
        cout<<"Hello World 2!"<<endl;
        T::print();
    }
};

class myClass{
public:
    void print(){
        cout<<"myClass"<<endl;
    }
};


int main()
{
    myClass my1;
    my1.print();
    cout<<"-----------------------"<<endl;
    DerivePrint1<myClass> my2;
    my2.print();
     cout<<"-----------------------"<<endl;
    DerivePrint2<myClass> my3;
    my3.print();
     cout<<"-----------------------"<<endl;
    DerivePrint2<DerivePrint1<myClass>> my4;
    my4.print();
     cout<<"-----------------------"<<endl;
    DerivePrint1<DerivePrint2<myClass>> my5;
    my5.print();
}

其输出结果如下:
myClass
-----------------------
Hello World 1!
myClass
-----------------------
Hello World 2!
myClass
-----------------------
Hello World 2!
Hello World 1!
myClass
-----------------------
Hello World 1!
Hello World 2!
myClass

可以看到,通过***parameterized inheritance***的方式实现mixin的设计,可以将多个独立的类综合起来,其中每个类就像是一个功能片段一样,且避免了多继承的风险,同时语义清晰,且允许线性化继承层级。


结论

mixin是一种设计思想,用于将相互独立的类的功能组合在一起,以一种安全的方式来模拟多重继承。而c++中mixin的实现通常采用Template Parameters as Base Classes的方法,既实现了多个不交叉的类的功能组合,又避免了多重继承的问题。

如要更深一层的了解mixin,了解Template Parameters as Base Classes,下方有几篇专门讲解mixin的博客:

此外,stackoverflow上也有几个问题值得参考,相较于系统性的博客,以下几个问答更简明:

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值