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
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;