C++模拟委托实现

来源:互联网 发布:怎么学习plc编程 编辑:程序博客网 时间:2024/04/28 13:03

最近这段时间在仿造.net的部分库,写一个小型的C++类库。既然要模仿.net,那么委托是少不了的。

本来想直接使用boost::function, 但他没有实现operator==, 不太好实现多播委托。

boost :: signal 库需要调用编译好的动态库,不符合我的要求,而且他的disconnect的实现让人很不满意,必须把在在调用connect时返回的哪个对象保存起来才能调用disconnect;

没办法,只有仿造function库重新写了一共,好像我考虑的系统只是2000以后的系统,和vc7.0以后的编译器,不用考虑编译器不支持偏特化的问题,今天捣鼓了一天,总算弄出来了

先看看如何使用

class A

{

public:

    void operator()(int&)

    {

        cout<<"A::operator()"<<endl;

    }

 

    void fun(int&)

    {

        cout<<"A::fun"<<endl;

    }

};

 

void fun(int&)

{

    cout<<"fun"<<endl;

}

 

int main()

{

 

    typedef winst::Delegate<void(int&)> Function;

 

    int i = 1;

    A a;

    Function  dop(&a);

    Function dmem(&A::fun, &a);

    Function dfree(fun);

 

    dop(i);

    dmem(i);

    dfree(i);

 

 

    dop += Function::MakeDelegate(fun);

    dmem += Function::MakeDelegate(fun);

 

    dop(i);

    dmem(i);

 

    cout<< (dop == dmem) <<endl;

    cout<< dop.Have(Function::MakeDelegate(fun))<<endl;

 

    dmem -= Function::MakeDelegate(&A::fun, &a);

    dmem(i);

}

 

实现的关键是

class Holder;

class A

{

public:

void fun(){};

};

A a;

Holder* holderPtr reinterpret_cast<Holder*>(&a);

void(Holder::*f)(void) = &A::fun;

(holderPtr->*)()//调用的时a.fun();

当调用a.fun()时,实际上是相当于g_fun(&a)

只要g_fun,a的地址正确,函数类型和参数类型不重要

这样就可以把函数对象,成员函数,自由函数保存下来

    template<typename R>

    class DelegateHolder<R(void)>

    {

    public:

        typedef R(MemberFunHolder::* MemberFun)(void);

        typedef R(*FreeFun)(void);

        typedef DelegateHolder<R(void)> ThisType;

        DelegateHolder(FreeFun fun)

        {

            MemberFun* f = reinterpret_cast<MemberFun*>(&fun);

            fun_ = *f;

            objPtr_ = 0;

        }

 

        template<typename T>

        DelegateHolder(R(T::*fun)(void), T* objPtr)

        {

           objPtr_ = reinterpret_cast<MemberFunHolder*>(objPtr);

           fun_ = reinterpret_cast<MemberFun>(fun);

        }

 

        template<typename T>

        DelegateHolder(T * objPtr)

        {

            objPtr_ = reinterpret_cast<MemberFunHolder*>(objPtr);

            fun_ = reinterpret_cast<MemberFun>(&T::operator());

        }

。。。。。。。。

        R operator()(void)

        {

            if(objPtr_ == 0)

            {

                FreeFun * f = reinterpret_cast<FreeFun*>(&fun_);

                FreeFun fun = *f;

                return fun();

            }

            else

            {

                return (objPtr_->*fun_)();

            }

        }

。。。。。。。。。。。。。。。

    private:

        MemberFunHolder * objPtr_; 

        MemberFun fun_;

};

 

还有一个问题是

class Arg1{};

class Arg2{};

class Arg3{};

 

template<typename A1 = Arg1, typename A2 = Arg2, typename A3 = Arg3>

class Test

{

public:

    void p(){cout<<"0"<<endl;}

};

 

template<typename A1>

class Test<A1(void), Arg2, Arg3>

{

public:

    void p() {cout<<"1"<<endl;}

};

 

template<typename A1, typename A2>

class Test<A1(A2)>

{

public:

void p() {cout<<"2"<<endl;}

};

 

Test<int(int)> t;

t.p(); // 2;

Test(int(void)> t2;

t2.p() //1

这样才能对“不同模板参数个数”的类实现特化。

下面时0参数实现的源码

  class MemberFunHolder{};

 

    namespace dele_arg

    {

        class Arg1{};

        class Arg2{};

        class Arg3{};

        class Arg4{};

        class Arg5{};

        class Arg6{};

        class Arg7{};

        class Arg8{};

        class Arg9{};

        class Arg10{};

    }

 

    template<typename R,

        typename Arg1 = dele_arg::Arg1,

        typename Arg2 = dele_arg::Arg2,

        typename Arg3 = dele_arg::Arg3,

        typename Arg4 = dele_arg::Arg4,

        typename Arg5 = dele_arg::Arg5,

        typename Arg6 = dele_arg::Arg6,

        typename Arg7 = dele_arg::Arg7,

        typename Arg8 = dele_arg::Arg8,

        typename Arg9 = dele_arg::Arg9,

        typename Arg10 = dele_arg::Arg10

    >

    class DelegateHolder;

   

    template<typename R,

        typename Arg1 = dele_arg::Arg1,

        typename Arg2 = dele_arg::Arg2,

        typename Arg3 = dele_arg::Arg3,

        typename Arg4 = dele_arg::Arg4,

        typename Arg5 = dele_arg::Arg5,

        typename Arg6 = dele_arg::Arg6,

        typename Arg7 = dele_arg::Arg7,

        typename Arg8 = dele_arg::Arg8,

        typename Arg9 = dele_arg::Arg9,

        typename Arg10 = dele_arg::Arg10

    >

    class Delegate;

 

    template<typename R>

    class DelegateHolder<R(void)>

    {

    public:

        typedef R(MemberFunHolder::* MemberFun)(void);

        typedef R(*FreeFun)(void);

        typedef DelegateHolder<R(void)> ThisType;

   

        DelegateHolder(const ThisType & other)

        {

            operator= (other);

        }

 

        DelegateHolder(FreeFun fun)

        {

            MemberFun* f = reinterpret_cast<MemberFun*>(&fun);

            fun_ = *f;

            objPtr_ = 0;

        }

 

        template<typename T>

        DelegateHolder(R(T::*fun)(void), T* objPtr)

        {

           objPtr_ = reinterpret_cast<MemberFunHolder*>(objPtr);

           fun_ = reinterpret_cast<MemberFun>(fun);

        }

 

        template<typename T>

        DelegateHolder(T * objPtr)

        {

            objPtr_ = reinterpret_cast<MemberFunHolder*>(objPtr);

            fun_ = reinterpret_cast<MemberFun>(&T::operator());

        }

 

        bool operator== (const ThisType & other) const

        {

            return (objPtr_ == other.objPtr_) && (fun_ == other.fun_);

        }

 

 

        bool operator!= (const ThisType & other) const

        {

            return ! operator== (other);

        }

 

        R operator()(void)

        {

            if(objPtr_ == 0)

            {

                FreeFun * f = reinterpret_cast<FreeFun*>(&fun_);

                FreeFun fun = *f;

                return fun();

            }

            else

            {

                return (objPtr_->*fun_)();

            }

        }

 

        DelegateHolder & operator= (const ThisType & other)

        {

            objPtr_ = other.objPtr_;

            fun_ = other.fun_;

            return *this;

        }

 

    private:

        MemberFunHolder * objPtr_; 

        MemberFun fun_;

    };

   

    template<typename R>

    class Delegate<R(void)>

    {

        typedef DelegateHolder<R(void)> Holder;

        typedef R(*FreeFun)(void);

        typedef Delegate<R(void)> ThisType;

    public:

 

        Delegate(const ThisType& other)

            :holder_(other.holder_)

        {

        }

 

        Delegate(Holder & holder)

            :holder_(holder)

        {

        }

 

        Delegate(FreeFun fun)

            :holder_(fun)

        {

        }

 

        template<typename T>

        Delegate(R(T::*fun)(void), T* objPtr)

            :holder_(fun, objPtr)

        {

        }

 

        template<typename T>

        Delegate(T * objPtr)

            :holder_(objPtr)

        {

        }

 

        Delegate & operator= (ThisType & other)

        {

            holder_ = other.holder_;

            return *this;

        }

 

        Delegate operator= (const Holder & holder)

        {

            holder_ = holder;

            return *this;

        }

 

        bool operator== (const ThisType& other) const

        {

            return holder_ == other.holder_;

        }

 

        bool operator != (const ThisType& other) const

        {

            return ! operator== (other);

        }

 

        bool operator== (const Holder & holder) const

        {

            return holder_ == holder;

        }

 

        bool operator!= (const Holder & holder) const

        {

            return ! operator== (holder)

        }

 

        R operator() ()

        {

            return holder_();

        }

 

    private:

        Holder holder_;

    };

 

    template<>

    class Delegate<void(void)>

    {

        typedef DelegateHolder<void(void)> Holder;

        typedef void(*FreeFun)(void);

        typedef Delegate<void(void)> ThisType;

    public:

         Delegate(ThisType & other)

             :holderList_(other.holderList_)

         {

         }

 

         Delegate(Holder& holder)

         {

             operator+= (holder);

         }

 

         Delegate(FreeFun fun)

         {

             Holder holder(fun);

             operator += (holder);

         }

 

         template<typename T>

         Delegate(void(T::*fun)(void), T* objPtr)

         {

             Holder holder(fun, objPtr);

             operator += (holder);

         }

 

        template<typename T>

        Delegate(T * objPtr)

        {

            Holder holder(objPtr);

            operator += (holder);

        }

 

         void operator += (Holder & holder)

         {

            if( FindHolder(holder) == false )

            {

                holderList_.push_back(holder);

            }

         }

 

         void operator -= (Holder & holder)

         {

             holderList_.remove(holder);

         }

 

         bool operator == (const ThisType & other) const

         {

             return holderList_ == other.holderList_;

         }

 

         bool operator != (const ThisType & other) const

         {

             return ! operator== (other);

         }

 

         bool operator == (const Holder & holder) const

         {

             if( holderList_.size() != 1 )

             {

                 return false;

             }

 

             return FindHolder(holder);

         }

 

         bool operator != (const Holder & holder) const

         {

             return !operator== (holder);

         }

 

         bool Have(Holder & holder)

         {

             return FindHolder(holder);

         }

 

         void operator() ()

         {

             foreach(Holder holder, holderList_)

             {

                 holder();

             }

         }

 

    public:

        static Holder MakeDelegate(FreeFun fun)

        {

            return Holder(fun);

        }

 

         template<typename T>

         static Holder MakeDelegate(void(T::*fun)(void), T* objPtr)

         {

             return Holder(fun, objPtr);

         }

 

         template<typename T>

         static Holder MakeDelegate(T * objPtr)

         {

             return Holder(objPtr);

         }

 

    private:

        bool FindHolder(const Holder & holderFind) const

        {

            foreach(Holder holder, holderList_)

            {

                if( holder == holderFind )

                {

                    return true;

                }

            }

 

            return false;

        }

 

    private:

        List<Holder> holderList_;

};

最后的工作就是定义一些宏来简化复制过程,然后复制,修改,实现1-10个参数的情况。还有就是要注意对象生存期的问题

 

 
原创粉丝点击