我们知道要使用一个函数指针,则必须声明一个函数指针类型,然后再定义一个函数指针变量。我们一般声明的函数指针,如:void (*funcPro)(int),那用这个函数指针类型定义的变量,可以指向一个“返回值是 void,带一个 int 类型的参数的函数”。假如要使用其他类型的返回值的,或是不同的参数类型的,那只能再去声明一个函数指针。今天看一种模板,它可以指定返回值和参数类型(及参数个数),然后就可以很轻松的定义出所需要的函数指针了。
首先看一个如何使用 boost (为什么使用 boost? 好像c++11里很多特性都是从boost代码移植的)里的类模板:
- //头文件Thread.h
-
- #ifndef __UNI_THREAD_H__
- #define __UNI_THREAD_H__
-
- #include
- #include
- #include
-
-
- class CThread: public boost::noncopyable
- {
- public:
- typedef boost::function0<void> threadProc;
- explicit CThread(const threadProc& proc, std::string threaName);
- ~CThread();
-
- void createThread();
-
- bool started()const
- {
- return mStarted;
- }
-
- pid_t tid() const
- {
- return mTid;
- }
-
- const std::string& name()const
- {
- return mName;
- }
-
- int join();
- private:
- static void* startThread(void* arg);
-
- void runInThread();
- private:
- bool mStarted;
- pthread_t mPthreadId;
- pid_t mTid;
- threadProc funcProc;
- std::string mName;
- };
-
- #endif
主要看 typedef boost::function0
我们看到它的类名是 BOOST_FUNCTION_FUNCTION,然而这个名称和 function0 有什么联系呢?这个其实是一个宏定义:
而 BOOST_JOIN 也是一个宏:
这些宏最终的目的是把 两个参数连在一起,即经过 BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) 后,BOOST_FUNCTION_FUNCTION=functionBOOST_FUNCTION_NUM_ARGS,而这个 BOOST_FUNCTION_NUM_ARGS 是一个宏,那这个宏是什么呢?
这是在 /usr/include/boost 目录下搜索出来的结果(我CentOS已经下载安装了 boost库,所以有这个目录),所以这个 BOOST_FUNCTION_NUM_ARGS 有可能是这些值,那也就是说BOOST_FUNCTION_FUNCTION=function0(或function1、function2、function3、function4、function5、function6、function7、function8、function9、function10)。那是不是有这些 functionX 模板定义呢?通过对上面的头文件 Thread.h 进行预编译:
g++ -std=c++11 -I./include -E ./include/Thread.h -o macroFunction
得到的文件 macroFunction 可以看到类模板的基本声明:
然后真正的 function0 模板定义为:
它其实就是:
- template<typename R>
- class function0 : public function_base
- {
-
- }
function1 类模板定义为:
function2 类模板的定义为:
function10 类模板的定义为:
所以经过预编译,已经生成了 11 个类模板的声明及定义。这样你就可以这样使用:
- typedef boost::function0<void> threadProc;
-
- //或
- typedef boost::function1<void, int> threadProc;
-
- //或
- typedef boost::function2<void, int, int> threadProc;
-
- //或
- typedef boost::function3<void, int, int, double> threadProc;
在使用的时候,模板名称中为0,1,2,3,... 10 表示除第一个外实参的个数,第一个表示返回值。如最开始代码中的使用:
- class CThread: public boost::noncopyable
- {
- public:
- typedef boost::function0<void> threadProc;
- explicit CThread(const threadProc& proc, std::string threaName);
构造函数CThread 的第一个参数就是一个类模板,使用:
- CThread::CThread(const threadProc& proc, std::string threaName):
- mStarted(false),
- mPthreadId(-1),
- funcProc(proc),
- mName(threaName)
- {
-
- }
-
- void CThread::createThread()
- {
- assert(!mStarted);
- mStarted = true;
-
- errno = pthread_create(&mPthreadId, NULL, startThread, this);
- if(errno < 0)
- {
-
- }
- }
-
- void* CThread::startThread(void* arg)
- {
- CThread *thread = static_cast
(arg); - thread->runInThread();
- return nullptr;
- }
-
- void CThread::runInThread()
- {
- mTid = CurrentThread::tid();
- if(funcProc)
- {
- funcProc();
- }
- }
创建线程后,执行线程函数,线程函数里调用了 funcProc(); 这里 funcProc 是一个类模板定义出来的类,像这种 funcProc() 来执行的方法,在c++里被称为仿函数,即变量是一个类,但可以像函数一样调用。那这个怎么实现的呢?其实就是重载了() ,这样在执行 funcProc() 时,就是调用类的重载 operator(),查看之前预编译的文件中有:
- result_type operator()( T0 a0 , T1 a1) const
- {
- if (this->empty())
- boost::throw_exception(bad_function_call());
-
- return get_vtable()->invoker
- (this->functor , a0 , a1);
- }
这个是 function2 类模板里的 operator() 重载。所以,经过上面这些介绍,我们可以知道,在经过预编译后,已经有了 function0~function10 的类模板了,只有在使用的时候才会生成对应的代码,即我这样使用:typedef boost::function2
这个boost库里的function代码看起来还是复杂的,而以前的老代码(c++11没出来前)也用到类似的模板,只是比这个简单,可读性也比较好。如下列的声明:
- //TFuction1
- #define FUNCTION_NUMBER 1
- #define FUNCTION_CLASS_TYPES typename R, typename T1
- #define FUNCTION_TYPES T1
- #define FUNCTION_TYPE_ARGS T1 a1
- #define FUNCTION_ARGS a1
- #define FUNCTION_CLASS_TYPE R, T1
- #include "FunctionTemplate.h"
- #undef FUNCTION_CLASS_TYPE
- #undef FUNCTION_NUMBER
- #undef FUNCTION_CLASS_TYPES
- #undef FUNCTION_TYPES
- #undef FUNCTION_TYPE_ARGS
- #undef FUNCTION_ARGS
-
- //TFuction2
- #define FUNCTION_NUMBER 2
- #define FUNCTION_CLASS_TYPES typename R, typename T1, typename T2
- #define FUNCTION_TYPES T1, T2
- #define FUNCTION_TYPE_ARGS T1 a1, T2 a2
- #define FUNCTION_ARGS a1, a2
- #define FUNCTION_CLASS_TYPE R, T1, T2
- #include "FunctionTemplate.h"
- #undef FUNCTION_CLASS_TYPE
- #undef FUNCTION_NUMBER
- #undef FUNCTION_CLASS_TYPES
- #undef FUNCTION_TYPES
- #undef FUNCTION_TYPE_ARGS
- #undef FUNCTION_ARGS
这个 FUNCTION_NUMBER 和 上面boost 代码里的 BOOST_FUNCTION_NUM_ARGS 是一样的,其类模板定义为:
也是一样,经过预编译,会生成 TFunction1、TFunctino2的定义,这样就可以使用了,讲到这里应该了解了这个 boost::functionX<> 的用法,其实现细节还需要仔细读代码,也可以参考这里:Member Function Pointers and the Fastest Possible C++ Delegates - CodeProject