一个CallBack函数模板
工作中经常需要调用一些老的库函数, 这些库函数又常常需要提供某种
回调函数(callback).比如在oldlib.h中定义了如下的函数:
//oldlib.h
typedef double (*Func) (double);
double _mean_value(double x0, double x1, Func f);
在使用_mean_value时, 我们需要提供一个Func型的回调函数。
现在假设我们开发了某个类SomeEngine
class SomeEngine
{
public:
...........
double EngineFunction(double x)
{
return x+mX;
};
double UseMeanValue()
{
return _mean_value(0, 1, EngineFunction); //(1)
}
private:
double mX;
};
我们希望在语句(1)中调用_mean_value时传递一个成员函数作为回调函数。然而
不幸的是(1)不能通过编译。虽然EngineFunction看起来与Func具有相同的参数
和返回值, 然而实际上它们是不同的函数类型, EngineFunction隐含了一个this指针。
现在我们来考虑如何饶过这个this指针问题。我们知道类的静态成员是不含this指针
的。好象我们可以这样写:
class SomeEngine
{
public:
...........
static double sEngineFunction(double x)
{
return EngineFunction(x); //(2)
}
double EngineFunction(double x)
{
return x+mX;
}
double UseMeanValue()
{
return _mean_value(0, 1, sEngineFunction);
}
private:
double mX;
};
现在(2)不能通过编译了, 因为静态成员函数不能访问非静态成员函数。如果我们能在(2)中获得this指针就好了, 这样 return this->EngineFunction(x)就没问题了。但是 静态成员函数不含this指针呀。(这个this真是麻烦:()。
办法总是有的, 现在我们给SomeEngine添加一个静态的指向自己的指针mspTHIS:
class SomeEngine
{
public:
...........
static double sEngineFunction(double x)
{
return mspTHIS->EngineFunction(x);
}
double EngineFunction(double x)
{
return x+mX;
}
double UseMeanValue()
{
mspTHIS = this;
return _mean_value(0, 1, sEngineFunction);
mspTHIS = NULL;
}
private:
double mX;
static SomeEngine* mspTHIS;
};
SomeEngine* SomeEngine::mspTHIS = NULL;
好了, 现在编译没有问题了, 程序也能够达到我们最初的目标。 不过回头看看,
仅仅为了传一个成员函数, 我们对SomeEngine的改动也太多了点(一个静态成员函数, 一个静态指针)。如果有另一个类也需要使用调用_mean_value(), 我们又得费一翻工夫, 重复劳动了。
这回我们要动用模板了。 下面给一个模板类, 来达到同样的目的, 具体细节就
不解释了.
//================================================================
// CLASS
// CallBackFunction<T, RT, PT>
// DESCRIPTION
// This template class is used as a convient wrapper
// for passing a non-static member function to an old C routine
// which requires a callback function.
// =============================================================
template
<
typename T,
typename ReturnT,
typename ParamT
>
class CallBackFunction
{
public:
typedef ReturnT (T::*MemberCallBackFunction)(ParamT);
typedef ReturnT (*CallBackFunc) (ParamT);
CallBackFunction(T* pT, MemberCallBackFunction memberCallBack)
{
mspT = pT;
mMemberCallBack = memberCallBack;
}
~CallBackFunction()
{
mspT = NULL;
mspTHIS = NULL;
}
operator CallBackFunc()
{
mspTHIS = this;
return CallBack;
}
private:
static ReturnT CallBack(ParamT x)
{
return (mspT->*(mspTHIS->mMemberCallBack))(x);
}
MemberCallBackFunction mMemberCallBack;
static T* mspT;
static CallBackFunction* mspTHIS;
// no implementations
CallBackFunction();
CallBackFunction(const CallBackFunction& rhs);
CallBackFunction<T, ReturnT, ParamT>& operator=(CallBackFunction<T, ReturnT, ParamT>& rhs);
};
template<typename T, typename ReturnT, typename ParamT>
T* CallBackFunction<T, ReturnT, ParamT>::mspT = NULL;
template<typename T, typename ReturnT, typename ParamT>
CallBackFunction<T, ReturnT, ParamT>* CallBackFunction<T, ReturnT, ParamT>::mspTHIS=NULL;
现在回到SomeEngine类, 看看如何使用上面的CallBackFunction<>。
class SomeEngine
{
public:
...........
double EngineFunction(double x)
{
return x+mX;
};
double UseMeanValue()
{
CallBackFunction<SomeEngine, double, double> engineFunction(this, &SomeEngine::EngineFunction);
return _mean_value(0, 1, engineFunction);
}
private:
double mX;
};
与最初的的SomeEngine比, 我们只添加了一行代码。这就是变化:
return _mean_value(0, 1, EngineFunction)
======>
CallBackFunction<SomeEngine, double, double> engineFunction(this, &SomeEngine::EngineFunction);
return _mean_value(0, 1, engineFunction);
没有static函数, 没有static指针, 世界清净了; 可以在任何类中使用, 可以偷懒了:))
///ps.
如果你使用了上述模板:
1。 如果你的机器爆了, 请你不要投诉我
2。 如果你中了500万大彩, 请给CSDN捐250万
:))))))))