mixin 实践

文章介绍了如何用C++中的模板来解决菱形继承导致的冲突问题。通过创建LoggingTask和TimingTask模板类,以及使用TaskAdaptor模板作为适配器,实现了对ITask接口的扩展,同时避免了不必要的开销和接口实现。这种方式利用组合和继承,实现了类似混合类型(mixin)的效果,允许在运行时添加logging和timing功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可以解决菱形继承等问题,代码如下

#include <iostream>
#include <memory>
#include <string>



using namespace  std;

struct ITask
{
    virtual ~ITask(){}
    virtual string GetName() = 0;
    virtual void Execute() = 0;
};

/* 需求:实现logging任务 和timing任务统计,有个实际的任务myTasK类要同时要使用二者的一些相同的接口,
最直观的是采用菱形继承,但是Execute会冲突
使用组合和继承的方式
*/
 /*....................................................................................
class LoggingTask : public ITask
{
    std::unique_ptr<ITask> mTask;
public:
    explicit LoggingTask(ITask* task):mTask(task){}

    void Execute() override
    {
        cout << "Logging: task start " << mTask->GetName() <<endl;
        if(mTask)
        {
            mTask->Execute();
        }
        cout << "Logging: task end " << mTask->GetName() <<endl;
    }

    string GetName() override
    {
        if(mTask)
        {
            return mTask->GetName();
        }
        else
        {
            return "unkown Logging task";
        }
    }
};


class TimingTask : public ITask
{
    std::unique_ptr<ITask> mTask;
public:
    explicit TimingTask(ITask* task):mTask(task){}

    void Execute() override
    {
        cout << "Time is 1 " <<endl;//简单点不引入time类了
        if(mTask)
        {
            mTask->Execute();
        }
        cout << "Time is 2" <<endl;
    }

    string GetName() override
    {
        if(mTask)
        {
            return mTask->GetName();
        }
        else
        {
            return "unkown Timeing task";
        }
    }
};

class MyTask : public ITask {
public:
    void Execute() override {
        std::cout << "...This is where the task is executed..." << std::endl;
    }
 
    std::string GetName() override {
        return "My task name";
    }
};

有不必要的开销:堆分配、null检查、虚函数。
像LoggingTask这样的类不想提供GetName这样的接口,但你继承自ITask就要实现这个接口。
假如ITask还有其它接口,LoggingTask都必须实现。
 ....................................................................................*/

 /* 使用mixin方式 如下*/

template<typename T>
class LoggingTask : public T
{
    public:
       void Execute()
       {
        cout << "Logging: task start " << T::GetName() <<endl;
        T::Execute();
        cout << "Logging: task end " << T::GetName() <<endl;
       }
};

template<typename T>
class TimingTask : public T
{
public:
       void Execute()
       {
        cout << "Time is 1 "  <<endl;
        T::Execute();
        cout << "Time is 2" << endl;
       }
};


class MyTask {
public:
    void Execute()  {
        std::cout << "...This is where the task is executed..." << std::endl;
    }
 
    std::string GetName() {
        return "My task name";
    }
};


//Task管理框架,因为它没实现ITask接口,这就是最后一个mixin的功能
template<typename T>
class TaskAdpter : public ITask, public T
{
public:
    void Execute() override
    {
        T::Execute();
    }

    string GetName() override
    {
        return T::GetName();
    }
};


int main()
{
    /* 组合加继承的方式
    unique_ptr<ITask> task(new LoggingTask(new TimingTask(new MyTask())));
    task->Execute();
    */
    MyTask t1;
    t1.Execute();

    TimingTask<MyTask> t2;
    t2.Execute();
    
    // A MyTask with added logging and timing:
    LoggingTask<TimingTask<MyTask>> t3;
    t3.Execute();
    
    // A MyTask with added logging and timing written to look a bit like the composition example
    using Task = LoggingTask<TimingTask<MyTask>> ;
    Task t4;
    t4.Execute();

    using LTMTask = TaskAdpter<LoggingTask<TimingTask<MyTask>>> ;
    LTMTask t;
    ITask* t5 = &t;
    t5->Execute();


    getchar();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值