当前位置:编程学习 > C/C++ >>

在C++中实现事件(委托)

 实现回调的三种方式(C风格的回调函数, Sink方式和Delegate方式)。在面向对象开发中,delegate的方式是最灵活和方便的,因此很早就有人用复杂的模板去模拟(有兴趣的话可以看这里和这里),总之是实现起来很复杂。但是现在借助C++11的function和bind, 我们可以很方便的去实现。下面是我自己的一种实现方式:
  namespace Common
{
    typedef void* cookie_type;
 
    template<typename TR, typename T1, typename T2>
    class CEvent
    {
    public:
        typedef TR return_type;
        typedef T1 first_type;
        typedef T2 second_type;
 
        typedef std::function<return_type (first_type, second_type)> handler_type;
 
        ~CEvent()
        {
            Clear();
        }
 
        return_type operator()(first_type p1, second_type p2)
        {
            return_type ret = return_type();
            size_t size = _handlers.size();
            for(size_t i=0; i<size; ++i)
            {
                ret = _handlers[i]->operator()(p1, p2);
            }
            return ret;
        }
 
        cookie_type AddHandler(std::function<return_type (first_type, second_type)> h)
        {
            CEventHandler*p = new(nothrow)  CEventHandler(h);
            if(p != nullptr) _handlers.push_back(p);
            return (cookie_type)p;
        }
 
        template<typename class_type, typename class_fun>
        cookie_type AddHandler(class_type* pThis, class_fun f)
        {
            CEventHandler* p = new(nothrow) CEventHandler(pThis, f);
            if(p != nullptr) _handlers.push_back(p);
            return (cookie_type)p;
        }
 
        void RemoveHandler(cookie_type cookie)
        {
            CEventHandler* p = (CEventHandler*)cookie;
 
            auto itr = std::find(_handlers.begin(), _handlers.end(), p);
            if(itr != _handlers.end())
            {
                _handlers.erase(itr);
                delete p;
            }
            else
            {
                assert(false);
            }
        }
 
        void Clear()
        {
            if(!_handlers.empty())
            {
                int n = _handlers.size();
                std::for_each(_handlers.begin(), _handlers.end(), [](CEventHandler* p)
                { 
                    assert(p != nullptr);
                    delete p;
                });
                _handlers.clear();        
            }
        }
 
    private:
        class CEventHandler 
        {
        public:
            CEventHandler(handler_type h)
            {
                _handler = h;
                assert(_handler != nullptr);
            }
 
            template<typename class_type, typename class_fun>
            CEventHandler(class_type* pThis, class_fun object_function)
            {
                using namespace std::placeholders;
                _handler = std::bind(object_function, pThis, _1, _2);
                assert(_handler != nullptr);
            }
 
            return_type operator()(first_type p1, second_type p2)
            {
                return_type ret = return_type();
                assert(_handler != nullptr);
                if(_handler != nullptr) ret = _handler(p1, p2);
                return ret;
            }
 
            handler_type _handler;
        };
 
 
    private:
        std::vector<CEventHandler*> _handlers;
    };
}
 
大概实现思想是我们通过一个内置的CEventHandler 类来封装处理函数,我们可以通过AddHandler来添加事件处理函数,添加时会返回一个Cookie,我们可以通过该Cookie来RemoveHandler, 下面是测试代码:
#include "stdafx.h"
#include <iostream>
#include "event1.h"
 
using namespace std;
 
class CObjectX 
{
 
};
 
class CClickEventArgs: public CObjectX
{
 
};
 
 
class CButton: public CObjectX
{
public:
    void FireClick()
    {
        CClickEventArgs args;
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,