在C++(www.cppentry.com)标准中,所有关于函数模板的API均在头文件funcitonal中,如mem_fun,函数模板主要的好处是将类的执行与具体类的实现分离开,这也是command设计模式中的一个关键特征.
在实现函数模式时,主要就是将类的实参及对象的指针进行保存起来,生成一个对象,到执行该函数时,不用显示原来的类执行函数,而是直接执行函数模板生成的对象即可.这样就实现了分离,那么函数模板的关键之处就是如何保存函数参数,及对象地址,返回数据.那么在涉及模板参数时,就至少有三种类型的参数:对象类型,参数类型及返回类型.
另外为了执行函数,就必须包含有函数指针,函数对应的行参及对象指针.而三种类型的参数就可以做为模板参数,后面的具体地址及内容就可以做为函数模板的具体构造函数来实现,为了保存具体的地址及行参,就需要定义模板类的私有成员来进行实现.所以,模板的具体定义(这里假设是单参数的函数模板)如下:
template <typename ResultType,typename ParamType,class PointerToObj>
class Functor_t {
private:
ParamType param1_;
PointerToObj* pObj_;
MemFn_t pMemFn_;
typedef ResultType (PointerToObj::*MemFn_t)(ParamType);
public:
Functor_t(PointerToObj *pObj,MemFn_t pMemFn,ParamType param1):param1_(param1),pMemFn_(pMemFn),pObj_(pObj)
{
}
另外还需要进行执行该函数的形式:obj(),直接通过重载运算符函数就可以实现:
ResultType operator()()
{
return (pObj_->*pMemFn_)(param1_);
}
这样就可以进行调用该函数了:
A a;
Functor_t<void,int,A> fn(&a,&A::print,2);
fn();
但是还有一点不足的是每次都需要指明函数模板的一些参数问题,有些不方便,不过这也是函数模板类的特点,可以对其进行封装采用非类模板:函数的形式来完成,这样就可以不用生成对象就可以进行调用:
template<class R,class T,class P> Functor_t<R,P,T> Functor(R (T::*f)(P),T* pT,P param)
{
return Functor_t<R,P,T>(pT,f,param);
}
这样在调用时,就不用具体指明参数的类型了:
Functor(&A::print,&a,2)();
采用了类似方法,可以构造无参数的函数模板,实现如下:
template <class R,class T>
class Fun_t
{
private:
R (T::*pmf)();
T *pT_;
public:
Fun_t(R (T::*f)(),T *pT):pmf(f),pT_(pT) {
}
R operator()()
{
return ((pT_->*pmf))();
}
};
template<class R,class T>
Fun_t<R,T> Fun(R (T::*f)(),T *pT)
{
return Fun_t<R,T>(f,pT);
}
采用类似方法可以进行扩展至多个参数,其中上面的测试结果如下:
print(i:2).
print(i:2).
no arguments
print(i:1).
sprintf 的小问题 (2012-08-23 17:24)
标签: snpritf 字符串数组初始化 分类: C++(www.cppentry.com)程序设计
最近需要将数组转换为字符串,就想到了库函数snprintf,sprintf,在使用sprintf的时候出现了一个奇怪的问题,程序如下:
#include <stdio.h>
#include <string.h>
#define N 5
int main(int argc,char *argv[])
{
int i = 0;//i = 2;
int a[N] = {0,1,2,3,4};
char str[N];
//memset(str,'\0',N 1);
for(; i < N; i)
{
sprintf(str i,“%d”,a[i]);
printf(“%d,%c,%d\n”,a[i],str[i],i);
}
puts(str);
return 0;
}