• C++03下的delegate实现-


    之前实现过C++11的delegate,为了学习,手动实现一个03版本的。

    没有可变模板参数,一切都是体力活。C++11下有function类,可以很轻松实现。于是从C++03开始,就从function造轮子。。

    function轮子的主要代码如下:

    #ifndef FUNCTION_CPLUSPLUS_03
    #define FUNCTION_CPLUSPLUS_03
    
    #include <iostream>
    using namespace std;
    
    namespace li
    { 
    
    //关于仿函数...可以显式指定 如 function<void(testClass1::*)(int,string)> f3( &testClass1::operator(), &tc0 );  或者function<void(testClass1::*)(int,string)> f3(&tc0);
    //关于拷贝构造等其他构造函数...太懒了...遇到坑再添加
    //已经添加有cv属性的类成员的情况
    
    //这里的function功能是没办法与C++11相比的,这里的function的主要目的是为实现delegate做类型擦除处理
    
    #define TEMPLATE_PARA0 typename R
    #define TEMPLATE_PARA1 TEMPLATE_PARA0 ,typename P1
    #define TEMPLATE_PARA2 TEMPLATE_PARA1 ,typename P2
    #define TEMPLATE_PARA3 TEMPLATE_PARA2 ,typename P3
    #define TEMPLATE_PARA4 TEMPLATE_PARA3 ,typename P4
    #define TEMPLATE_PARA5 TEMPLATE_PARA4 ,typename P5
    #define TEMPLATE_PARA6 TEMPLATE_PARA5 ,typename P6
    #define TEMPLATE_PARA7 TEMPLATE_PARA6 ,typename P7
    #define TEMPLATE_PARA8 TEMPLATE_PARA7 ,typename P8
    
    #define TEMPLATE_PARA0_INS
    #define TEMPLATE_PARA1_INS P1 p1
    #define TEMPLATE_PARA2_INS TEMPLATE_PARA1_INS , P2 p2
    #define TEMPLATE_PARA3_INS TEMPLATE_PARA2_INS , P3 p3
    #define TEMPLATE_PARA4_INS TEMPLATE_PARA3_INS , P4 p4
    #define TEMPLATE_PARA5_INS TEMPLATE_PARA4_INS , P5 p5
    #define TEMPLATE_PARA6_INS TEMPLATE_PARA5_INS , P6 p6
    #define TEMPLATE_PARA7_INS TEMPLATE_PARA6_INS , P6 p7
    #define TEMPLATE_PARA8_INS TEMPLATE_PARA7_INS , P6 p8
    
    #define TEMPLATE_PARA0_N R
    #define TEMPLATE_PARA1_N TEMPLATE_PARA0_N , P1
    #define TEMPLATE_PARA2_N TEMPLATE_PARA1_N , P2
    #define TEMPLATE_PARA3_N TEMPLATE_PARA2_N , P3
    #define TEMPLATE_PARA4_N TEMPLATE_PARA3_N , P4
    #define TEMPLATE_PARA5_N TEMPLATE_PARA4_N , P5
    #define TEMPLATE_PARA6_N TEMPLATE_PARA5_N , P6
    #define TEMPLATE_PARA7_N TEMPLATE_PARA6_N , P7
    #define TEMPLATE_PARA8_N TEMPLATE_PARA7_N , P8
    
    enum FunType
    {
        Normal,
        Member
    };
    
    template<typename R,typename P1=void,typename P2=void,typename P3=void,
        typename P4=void,typename P5=void,typename P6=void,typename P7=void,typename P8=void,typename P9=void>
    class function_impl;
     
    
    #define FUNCTION_IMPL(id)   
    template<TEMPLATE_PARA##id> 
    class function_impl<TEMPLATE_PARA##id##_N>  
    { 
    public: 
    function_impl(){};  
    virtual R operator()(TEMPLATE_PARA##id##_INS)=0;  
        virtual ~function_impl(){}; 
        virtual FunType getFunType(){return Normal;}
    };  
    
    
      
    FUNCTION_IMPL(0)
    FUNCTION_IMPL(1)
    FUNCTION_IMPL(2)
    FUNCTION_IMPL(3)
    FUNCTION_IMPL(4)
    FUNCTION_IMPL(5)
    FUNCTION_IMPL(6)
    FUNCTION_IMPL(7)
    FUNCTION_IMPL(8)
    /**************************************************************************************************/
     
    
    template<typename F>
    class function;
     
    #define TEMPLATE_PARA0_N1 
    #define TEMPLATE_PARA1_N1  P1
    #define TEMPLATE_PARA2_N1 TEMPLATE_PARA1_N1 , P2
    #define TEMPLATE_PARA3_N1 TEMPLATE_PARA2_N1 , P3
    #define TEMPLATE_PARA4_N1 TEMPLATE_PARA3_N1 , P4
    #define TEMPLATE_PARA5_N1 TEMPLATE_PARA4_N1 , P5
    #define TEMPLATE_PARA6_N1 TEMPLATE_PARA5_N1 , P6
    #define TEMPLATE_PARA7_N1 TEMPLATE_PARA6_N1 , P7
    #define TEMPLATE_PARA8_N1 TEMPLATE_PARA7_N1 , P8
    
    #define PARA_LIST0
    #define PARA_LIST1 p1
    #define PARA_LIST2 PARA_LIST1 ,p2
    #define PARA_LIST3 PARA_LIST2 ,p3
    #define PARA_LIST4 PARA_LIST3 ,p4
    #define PARA_LIST5 PARA_LIST4 ,p5
    #define PARA_LIST6 PARA_LIST5 ,p6
    #define PARA_LIST7 PARA_LIST6 ,p7
    #define PARA_LIST8 PARA_LIST7 ,p8
    
    #define FUNCTION(id) 
    template<TEMPLATE_PARA##id> 
    class function<R(TEMPLATE_PARA##id##_N1)> :public function_impl<TEMPLATE_PARA##id##_N> 
    {  
    public:
    typedef R(*F)(TEMPLATE_PARA##id##_N1);
        function(F f):func_(f){ };
        R operator()(TEMPLATE_PARA##id##_INS) {return func_(PARA_LIST##id);}
        void* getTarget()const
    {
        return (void*)*func_;
    }
        F func_; 
    };
    
    
    FUNCTION(0) 
    FUNCTION(1)
    FUNCTION(2)
    FUNCTION(3)
    FUNCTION(4)
    FUNCTION(5)
    FUNCTION(6)
    FUNCTION(7)
    FUNCTION(8)
     
     
    
    /**************************************************************************************************/
    
    #define FUNCTION_MEM(id,...) 
        template<class C, TEMPLATE_PARA##id> 
    class function<R(C::*)(TEMPLATE_PARA##id##_N1)__VA_ARGS__> :public function_impl<TEMPLATE_PARA##id##_N>  
    {  
    public: 
        typedef R(C::*F)(TEMPLATE_PARA##id##_N1)__VA_ARGS__; 
        typedef C*  CPtr; 
        function(F f,C*cp):func_(f),c_ptr(cp){}; 
        function(C*cp):func_( &C::operator()),c_ptr(cp){}; 
        R operator()(TEMPLATE_PARA##id##_INS) 
    { 
        return (c_ptr->*func_)(PARA_LIST##id); 
    } 
      FunType getFunType(){return Member;}
     F getTarget()const
    {
    return func_;
    }
     CPtr getTarCalssPtr() const
    {
        return c_ptr;
    }
    protected: 
        F func_; 
        CPtr c_ptr;
    };
    
     
     FUNCTION_MEM(0)
     FUNCTION_MEM(1)
     FUNCTION_MEM(2)
     FUNCTION_MEM(3)
     FUNCTION_MEM(4)
     FUNCTION_MEM(5)
     FUNCTION_MEM(6)
     FUNCTION_MEM(7)
     FUNCTION_MEM(8)
    
    
     FUNCTION_MEM(0,const) 
     FUNCTION_MEM(1,const)
     FUNCTION_MEM(2,const)
     FUNCTION_MEM(3,const)
     FUNCTION_MEM(4,const)
     FUNCTION_MEM(5,const)
     FUNCTION_MEM(6,const)
     FUNCTION_MEM(7,const)
     FUNCTION_MEM(8,const)
    
    
     FUNCTION_MEM(0,volatile) 
     FUNCTION_MEM(1,volatile)
     FUNCTION_MEM(2,volatile)
     FUNCTION_MEM(3,volatile)
     FUNCTION_MEM(4,volatile)
     FUNCTION_MEM(5,volatile)
     FUNCTION_MEM(6,volatile)
     FUNCTION_MEM(7,volatile)
     FUNCTION_MEM(8,volatile)
    
     FUNCTION_MEM(0,const volatile) 
     FUNCTION_MEM(1,const volatile)
     FUNCTION_MEM(2,const volatile)
     FUNCTION_MEM(3,const volatile)
     FUNCTION_MEM(4,const volatile)
     FUNCTION_MEM(5,const volatile)
     FUNCTION_MEM(6,const volatile)
     FUNCTION_MEM(7,const volatile)
     FUNCTION_MEM(8,const volatile)
      
     };
    #endif

    然后再来造delegate的轮子,代码如下:

    #ifndef DELEGATE_CPLUSPLUS_03
    #define DELEGATE_CPLUSPLUS_03
    
    #include "function.hpp"
    #include <list>
    #include <iostream>
    using namespace std;
    
    namespace li
    {
         
        //此处参考 《Modern C++ Design》 一书,牛人牛书啊,不过这里暂时没用到,之前想的情况比较复杂,以为会用到,代码还是比较经典的,所有保留在此
    
        /*判断类型之间能否相互转换*/
        template<class T, class U>
        class Convert 
        {  
            static char Test(U); 
            static int Test(...); 
            static T MakeT(); 
        public: 
            enum { CanConvert =sizeof(Test(MakeT())) == sizeof(char) };  
        }; 
         
    
    template<typename R=void,typename P1=void,typename P2=void,typename P3=void,
        typename P4=void,typename P5=void,typename P6=void,typename P7=void,typename P8=void,typename P9=void>
        class delegate;
         
        template<typename F,typename C>
        class deleMemHelper
        {
        public:
            deleMemHelper(F f,C*cptr):fun(f),c_ptr(cptr){}
            F fun;
            C*c_ptr;
        };
    
        template<typename F,typename C>
        deleMemHelper<F,C> makeDeleMemHelper(F f,C*cp)
        {
        return deleMemHelper<F,C>(f,cp);
        }
    
    #define DELEGATE_CLASS(id) 
        template<TEMPLATE_PARA##id> 
        class delegate<R(TEMPLATE_PARA##id##_N1)> 
        { 
        public: 
        typedef li::function_impl<TEMPLATE_PARA##id##_N> dele_func;
        typedef std::list<dele_func*> function_list;
        typedef R(*func_type)(TEMPLATE_PARA##id##_N1);
        typedef delegate<R(TEMPLATE_PARA##id##_N1)>  this_type;
        
        delegate(){};
        ~delegate()
        {
          clear();
        }
        
        
        void clear()
        {
           for(typename function_list::iterator itr =func_list.begin();itr!= func_list.end(); itr++ )
           {
             delete *itr;
           }
           func_list.clear();
        }
        
        this_type& operator+=(func_type fun)
        {
        func_list.push_back(new function<R(TEMPLATE_PARA##id##_N1)>(fun));
        return *this;
        }
        this_type& operator-=(func_type fun)
        {
        for( function_list::iterator itr = func_list.begin(); itr!= func_list.end(); ++itr )
        {
          if((*itr)->getFunType()!=Normal) continue;
           func_type p =(func_type)( ((function<R(TEMPLATE_PARA##id##_N1)>*)(*itr))->getTarget());
           if(p && *p==fun)
           {
             delete *itr;
             func_list.erase(itr);
             break;
           }
        }
        return *this;
        }
        
        template<class C,class B>
        this_type& operator+=(const deleMemHelper<R(C::*)(TEMPLATE_PARA##id##_N1),B>& delemh)
        {
          C* c_ptr = dynamic_cast<C*>(delemh.c_ptr);
          if(!c_ptr) return *this;
        func_list.push_back(new function<R(C::*)(TEMPLATE_PARA##id##_N1)>(delemh.fun, c_ptr));
        return *this;
        }
        
        template<class C,class B>
            this_type& operator-=(const deleMemHelper<R(C::*)(TEMPLATE_PARA##id##_N1),B>& delemh)
        {
           for( function_list::iterator itr = func_list.begin(); itr!= func_list.end(); ++itr )
          {
             if((*itr)->getFunType()==Normal) continue;
             function<R(C::*)(TEMPLATE_PARA##id##_N1)>*func = dynamic_cast<function<R(C::*)(TEMPLATE_PARA##id##_N1)>*>(*itr);
             if(func==NULL) continue;
              C*cp =func->getTarCalssPtr();
              if(cp&& cp==delemh.c_ptr )
              {
               if( func->getTarget() == delemh.fun )
               {
                    delete *itr;  
                    func_list.erase(itr);
                    break;
               }
               
             }
          }
        return *this;
        }
        
        
        void operator()(TEMPLATE_PARA##id##_INS)
        {
        for (typename function_list::iterator itr = func_list.begin(); itr != func_list.end(); itr++)
        {
        try
        {
        (*(*itr))(PARA_LIST##id);
        }
        catch (exception ex)
        {
        
        }
        }
        }
        private: 
         function_list func_list;
        }; 
    
      
    DELEGATE_CLASS(0)
    DELEGATE_CLASS(1)
    DELEGATE_CLASS(2)
    DELEGATE_CLASS(3)
    DELEGATE_CLASS(4)
    DELEGATE_CLASS(5)
    DELEGATE_CLASS(6)
    DELEGATE_CLASS(7)
    DELEGATE_CLASS(8)
    
    };
    #endif

    测试用例如下:

     
    #include "function.hpp" 
    #include "delegate.hpp"
    #include <string>
    #include <iostream>
     
    using namespace std;
    using namespace li;
    
    void funTest(int a,string b)
    {
         cout<<"funTest"<<"  "<<a<<endl; 
    }
    
    
    class testClass
    {
    public:
        testClass(int i):i(i){}
        void funTest(int a,string b)
        {
            cout<<"testClass  "<< i<<"    "<<a <<"    "<<b<<endl;
        }
        int i;
    };
    
    class A
    {
       public:
        virtual void funTest(int a,string b)
        {
            cout<<"A虚函数测试  "<< "    "<<a <<"    "<<b<<endl;
        }
    };
    
    class C:public    A
    {
    public:
        void funTest(int a,string b)
        {
            cout<<"C虚函数测试  "<< "    "<<a <<"    "<<b<<endl;
        }
    };
    
    
    
    class testClass1
    {
    public:
        testClass1(int i):i(i){}
        void funTest(int a,string b)
        {
            cout<<"testClass1  "<< i<<"    "<<a <<"    "<<b<<endl;
        }
    
        void operator()(int a,string b)
        {
            cout<<"testClass1 operator()  "<< i<<"    "<<a <<"    "<<b<<endl;
        }
    
        int i;
    };
    
    int sft(int a, const string& b,double c)
    { 
        cout<<a<<"  "<< b<<"  "<<c<<endl;
        return 3333;
    }
    
    int sft1(int a, const string& b,double c,C &)
    { 
        return 3333;
    }
     
     
    int main(int argc, char* argv[])
    {       
         function<int(int, const string&,double)>  f = sft;
         function<int(int, const string&,double,C&)>  f1 = sft1;
          
         f(4,string("asdfasdfasdfasdfasdfasdfas"),.0333); 
    
         testClass1 tc0(3);
    
         function<void(testClass1::*)(int,string)> f3( &testClass1::operator(), &tc0 );
         f3(99,"");
    
         function<void(testClass1::*)(int,string)> f4(&tc0);
         f4(98,"d");
         cout<<"*********************单个函数测试完*******************"<<endl;
    
        testClass tc(1);
        testClass tc1(2);
         
        testClass1 tc21(1);
        testClass1 tc22(2);
         
     
        C c;
    
        delegate<void(int,string)> de; 
     
    
        de+=funTest;
        de+=makeDeleMemHelper(&testClass::funTest,&tc);
        de+=makeDeleMemHelper(&testClass::funTest,&tc1);
        de+=makeDeleMemHelper(&C::funTest,&c);
        de(3,"afasdfasdfas");
        cout<<"***********************************************************"<<endl;
      
        de-=funTest; 
        de+=makeDeleMemHelper(&testClass1::funTest,&tc21);
        de(4,"afasdfasdfas");
        cout<<"***********************************************************"<<endl;
     
        de-=makeDeleMemHelper(&testClass::funTest,&tc);
        de+=makeDeleMemHelper(&testClass1::funTest,&tc22);
        de+=funTest;
         de(5,"afasdfasdfas");
        cout<<"***********************************************************"<<endl;
       
        de-=makeDeleMemHelper(&testClass::funTest,&tc1); 
        de-=makeDeleMemHelper(&testClass1::funTest,&tc22); 
        de-=makeDeleMemHelper(&C::funTest,&c);
        de(6,"afasdfasdfas");
        cout<<"***********************************************************"<<endl;
        de.clear();
        de(7,"asdfa");
        cout<<"*******************end end end************************"<<endl;
        return 0;
    }

    测试编译器VS2010 ,测试结果如下:

    详细代码说明如下:

    未完待续。。。

  • 相关阅读:
    基于接口而非实现编程 和 依赖注入
    程序出错该返回啥?
    js关于for循环实现线程休眠效果的问题
    预祝1024节日快乐!
    20201101_Python的虚拟环境问题
    机器学习——dbscan密度聚类
    公司里使用gitlab管理项目
    MYSQL集群MHA架构实现手册
    vbox导入虚拟电脑网卡MAC问题,MacOS 通过virtualbox安装的centos7虚拟机不能上网解决
    MySQL误操作后如何快速回滚(转)
  • 原文地址:https://www.cnblogs.com/lxzCode/p/3741335.html
Copyright © 2020-2023  润新知