1. 程式人生 > >C++模擬委託實現

C++模擬委託實現

最近這段時間在仿造.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;

Functiondop(&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;