c++多态,回调,和策略模式

熟悉高级语言像c#的人应该都知道,c#中有事件的机制,qt有信号槽的机制,设想我们有个简单的任务,窗口上一个按钮,按钮内部是一个button类,我们用鼠标点击一下他,他会发出一个鼠标点击的通知,我们需要在这个通知里面做一些自己的事情。我大概总结了三种方法。

1 多态

这是最一般的方法,继承button,利用多态性质覆盖button中鼠标点击的虚方法,在虚方法里面写自己的代码即可。

2 回调

可是我们要是这样做,我们就无法方便的取到放在窗口类里面的公共数据了,这就是多态的一个不好的地方。像这样一个简单的任务,还是用回调的机制比较好一点。回调类似c#中的事件机制,在c++里实现,我们首先提供一个回调注册的方法,将回调对象保存起来,然后在事件发生的时候调用他就可以啦。回调对象用boos::funcktion类型来表达,回调对象可以是函数指针,函数对象,类成员函数,lamda表达式。

class baseClass
{
public:
    typedef boost::function<int(std::string&)> CBFunc;
    baseClass()
    {

    }
    void RaiseEvent(std::string& str)
    {
        if(cb)
            cb(str);
    }

    void registerCB(CBFunc cb)
    {
        this->cb=cb;
    }

private:
    CBFunc cb;
};

int main()
{
    baseClass bc;
    bc.registerCB([](std::string& a){std::cout<<a<<std::endl;return 0;});
    std::string info("fuck you");
    bc.RaiseEvent(info);
}

3 策略模式

上面两种方法可以解决大部分应用场合,但考虑到这样一种应用场合,你需要编写一个画图程序,有不同的工具,画矩形的,画圆的,变形的,拖动的等,你是在一个panel上面绘制。这时候怎么办?最原始的办法档让就是设置一个标记,记下当下选择的是什么工具,然后在panel的鼠标事件里进去区分,如果是判断是画圆的,就在鼠标点击的时候放一个圆对象,拖动的时候缩放;如果是画框的有不一样。如果你这样写,等你下次要扩充一个工具的时候,就累死了。因为你各种鼠标事件里面都要改一遍。优雅的实现方式是这样,你定义个事件接口,里面有各种鼠标事件,鼠标按下,鼠标释放,鼠标移动等,然后不同的工具进行不同的实现,每一个成为一个工具类,标准叫法是事件处理器,你将这个事件处理器在用户选择工具时传递给panel,panel在自身的事件里面调用事件处理器里面的相应的方法。因此工具类就可以获取到各种事件了。他可以在里面自定义自己的操作。选择不同的工具只需要切换不同的事件处理器给panel就行了,是不是很魔幻?下面上代码解释

class IEventhandle
{
public :
    virtual void onEvent1()=0;
    virtual void onEvent2()=0;
    virtual void onEvent3()=0;
};
class myEventhandle:public IEventhandle
{
public:
    void onEvent1()
    {
        std::cout<<"me fuck event 1"<<std::endl;
    }
    void onEvent2()
    {
        std::cout<<"me fuck event 2"<<std::endl;
    }
    void onEvent3()
    {
        std::cout<<"me fuck event 3"<<std::endl;
    }
};
class youEventhandle:public IEventhandle
{
public:
    void onEvent1()
    {
        std::cout<<"you fuck event 1"<<std::endl;
    }
    void onEvent2()
    {
        std::cout<<"you fuck event 2"<<std::endl;
    }
    void onEvent3()
    {
        std::cout<<"you fuck event 3"<<std::endl;
    }
};

class baseClass
{
public:
    baseClass():handle(NULL)
    {

    }
    void RaiseEvent1()
    {
        if(handle)
            handle->onEvent1();
    }
    void RaiseEvent2()
    {
        if(handle)
            handle->onEvent2();
    }
    void RaiseEvent3()
    {
        if(handle)
            handle->onEvent3();
    }

    void registerHandle(IEventhandle* hd)
    {
        this->handle=hd;
    }

private:
    IEventhandle* handle;
};

int main()
{
    baseClass bc;
    myEventhandle mh;
    bc.registerHandle(&mh);
    bc.RaiseEvent1();
    bc.RaiseEvent2();
    bc.RaiseEvent3();

    youEventhandle yh;
    bc.registerHandle(&yh);
    bc.RaiseEvent1();
    bc.RaiseEvent2();
    bc.RaiseEvent3();
}
ok,这就是事实的全部真相,c#中能实现的,c++照样可以,c++中可以实现的c#不一定可以。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值