使用仿函数封装C和C++函数指针
http://blog.csdn.net/luckheadline
1. 什么是仿函数
仿函数是带有状态的函数。在C++中,可以认为它们是带有一个或多个存储有状态的私有成员和带有个一个重载操作符()以执行函数的类。仿函数可以使用模板和多态的概念封装C和C++函数指针。我们可以为任意类建立一个成员函数指针列表,然后通过相同的接口调用它们而不影响它们的类。所有的函数需要有相同的返回值和调用参数。有时候仿函数也称闭包。我们也可以用仿函数实现callback。
2. 如何实现仿函数
首先需要一个基类TFunctor,它提供一个虚函数Call或者虚重载符(),使用它可以调用成员函数。至于是喜欢用重载操作符还是调用Call函数取决于你。从基类可以继承一个模板类TSpecificFunctor,它在构造函数中用一个指向对象的指针和一个成员函数指针初始化。这个继承类重载了函数Call和/或基类的操作符():在重载版本中,使用指向对象的存储指针和成员函数指针调用成员函数。
//-----------------------------------------------------------------------------------------
// 4.2 How to Implement Functors
// abstract base class
class TFunctor
{
public:
// two possible functions to call member function. virtual cause derived
// classes will use a pointer to an object and a pointer to a member function
// to make the function call
virtual void operator()(const char* string)=0; // call using operator
virtual void Call(const char* string)=0; // call using function
};
// derived template class
template <class TClass> class TSpecificFunctor : public TFunctor
{
private:
void (TClass::*fpt)(const char*); // pointer to member function
TClass* pt2Object; // pointer to object
public:
// constructor - takes pointer to an object and pointer to a member and stores
// them in two private variables
TSpecificFunctor(TClass* _pt2Object, void(TClass::*_fpt)(const char*))
{ pt2Object = _pt2Object; fpt=_fpt; };
// override operator "()"
virtual void operator()(const char* string)
{ (*pt2Object.*fpt)(string);}; // execute member function
// override function "Call"
virtual void Call(const char* string)
{ (*pt2Object.*fpt)(string);}; // execute member function
};
3. 如何使用仿函数的例子
下面的例子中,有两个类,提供了函数Display。我们建立指向TFunctor指针的数组并且用两个指向TSpecificFunctor指针初始数组的entries。然后使用仿函数组调用各自的成员函数。不需要指向对象的指针调用函数并且不用再关心那些类了。
//-----------------------------------------------------------------------------------------
// 4.3 Example of How to Use Functors
// dummy class A
class TClassA{
public:
TClassA(){};
void Display(const char* text) { cout << text << endl; };
/* more of TClassA */
};
// dummy class B
class TClassB{
public:
TClassB(){};
void Display(const char* text) { cout << text << endl; };
/* more of TClassB */
};
// main program
int main(int /*argc*/, char* /*argv[]*/)
{
// 1. instantiate objects of TClassA and TClassB
TClassA objA;
TClassB objB;
// 2. instantiate TSpecificFunctor objects ...
// a ) functor which encapsulates pointer to object and to member of TClassA
TSpecificFunctor<TClassA> specFuncA(&objA, &TClassA::Display);
// b) functor which encapsulates pointer to object and to member of TClassB
TSpecificFunctor<TClassB> specFuncB(&objB, &TClassB::Display);
// 3. make array with pointers to TFunctor, the base class, and initialize it
TFunctor* vTable[] = { &specFuncA, &specFuncB };
// 4. use array to call member functions without the need of an object
vTable[0]->Call("TClassA::Display called!"); // via function "Call"
(*vTable[1]) ("TClassB::Display called!"); // via operator "()"
// hit enter to terminate
cout << endl << "Hit Enter to terminate!" << endl;
cin.get();
return 0;
}