读书人

一个CallBack函数模板解决方法

发布时间: 2012-03-09 21:42:54 作者: rapoo

一个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万
:))))))))



[解决办法]
这个模板要想真有实用价值,代码量就是boost function库的大小,文件加起来一共62K,还不算调的boost库其它组件的大小。
[解决办法]
没没看完...
[解决办法]

[解决办法]
mark.
[解决办法]
好麻烦啊
[解决办法]
MARK!

读书人网 >C++

热点推荐