c++ 泛型 编程 之 Functor 设计模式
2015-02-25 17:32
288 查看
完整代码见: http://download.csdn.net/detail/zhuyingqingfen/8457091
测试:
#ifndef FUNCTOR_H_ #define FUNCTOR_H_ #include "typelists.h" #include "typetraits.h" template<typename R,class TList>class FunctorImpl; template<typename R> class FunctorImpl<R,NullType> { public: virtual R operator()() = 0; //Clone 目的是为了产生FunctorImpl对象的一份多态(通过基类指针调用实际的对象的Clone方法)拷贝 //这个也用到了“协变式返回类型"特性,即你可以在子类中改写返回值类型,指向子类(pointer to derived class) virtual FunctorImpl * Clone()const = 0; virtual ~FunctorImpl(){}//虚构造函数的作用是当删除FunctorImpl的指针时,能够调用FunctorImpl的 //派生类的指针。 }; template<typename R,typename P1> class FunctorImpl<R,TYPELIST_1(P1)> { public: virtual R operator()(P1) = 0; virtual FunctorImpl * Clone()const = 0; virtual ~FunctorImpl(){} }; template<typename R,typename P1,typename P2> class FunctorImpl<R,TYPELIST_2(P1,P2)> { public: virtual R operator()(P1,P2) = 0; virtual FunctorImpl * Clone()const = 0; virtual ~FunctorImpl(){} }; template<class ParentFunctor,typename Fun> class FunctorHandler://普通函数实现 public FunctorImpl<typename ParentFunctor::ResultType,typename ParentFunctor::ParmList> { public: typedef typename ParentFunctor::ResultType ResultType; FunctorHandler(const Fun & fun):_fun(fun){} FunctorHandler*Clone()const{return new FunctorHandler(*this);} ResultType operator()(){return _fun;} ResultType operator()(typename ParentFunctor::Parm1 p1){return _fun(p1);} ResultType operator()(typename ParentFunctor::Parm1 p1,typename ParentFunctor::Parm2 p2) { return _fun(p1,p2); } private: Fun _fun; }; template<class ParentFunctor,typename PointerToObj,typename PointerToMemFn> class MemFunHandler : public FunctorImpl<typename ParentFunctor::ResultType,typename ParentFunctor::ParmList> { public: typedef typename ParentFunctor::ResultType ResultType; MemFunHandler(const PointerToObj & pOjb,PointerToMemFn pMemFn) :_pObj(pOjb),_pMemFn(pMemFn){} MemFunHandler * Clone()const {return new MemFunHandler(*this);} ResultType operator()(){return ((*_pObj).*_pMemFn)();} ResultType operator()(typename ParentFunctor::Parm1 p1) {return ((*_pObj).*_pMemFn)(p1);} ResultType operator()(typename ParentFunctor::Parm1,typename ParentFunctor::Parm2) {return ((*_pObj).*_pMemFn)(p1,p2);} private: PointerToObj _pObj; PointerToMemFn _pMemFn; }; template<typename R,class TList> class Functor { public: typedef R ResultType; typedef TList ParmList; typedef typename TypeAtNonStrict<TList,0,EmptyType>::Result Parm1; typedef typename TypeAtNonStrict<TList,1,EmptyType>::Result Parm2; //用来处理仿函数和普通函数 template<typename Fun> explicit Functor(const Fun & fun) :spImpl(new FunctorHandler<Functor,Fun>(fun)) { } //用来处理普通类成员函数 template <class P, typename MF> explicit Functor(P const& pobj, MF memfun) :spImpl(new MemFunHandler<Functor,P,MF>(pobj,memfun)) { } Functor():spImpl(0) { } Functor(const Functor & src) { spImpl = src.spImpl?src.spImpl->Clone():NULL; } Functor& operator = (const Functor &) { if (this != &src) { if (spImpl) delete spImpl; spImpl = src.spImpl? src.spImpl->Clone():NULL; } return *this; } R operator()(){return (*spImpl)();} R operator()(Parm1 p1){return (*spImpl)(p1);} R operator()(Parm1 p1,Parm2 p2){return (*spImpl)(p1,p2);} private: typedef FunctorImpl<R,TList> Impl; std::auto_ptr<Impl>spImpl; }; #endif
测试:
struct TestFunctor{ void operator()(int i,double d) { std::cout<<"test functor:"<<i<<" "<<d<<std::endl; } }; void MysimpleFunction(int i,double d) { std::cout<<"test functor:"<<i<<" "<<d<<std::endl; } class MyClass { public: void test(int i){std::cout<<i<<std::endl;} void print(){std::cout<<"Myclass:print()"<<std::endl;} }; void functor_test() { std::cout<<"Functor Test:-----------"<<std::endl; TestFunctor f; Functor<void, TYPELIST_2(int,double)>cmd(f); typedef void (*PFun)(int,double); PFun pf = MysimpleFunction; /*(摘自网络) 按照&运算符本来的意义,它要求其操作数是一个对象,但函数名不是对象(函数是一个对象),本来&test是非法的,但很久以前有些编译器已经允许这样做, c/c++标准的制定者出于对象的概念已经有所发展的缘故,也承认了&test的合法性。 因此,对于test和&test你应该这样理解,test是函数的首地址,它的类型是void (),&test表示一个指向函数test这个对象的地址, 它的类型是void (*)(),因此test和&test所代表的地址值是一样的,但类型不一样。test是一个函数,&test表达式的值是一个指针! 跟此问题类似的还有对一个数组名取地址。 int a[100]; printf("%p\n", a); printf("%p\n", &a[0]); 打印值一样。 但是数组名a,指向的是具有100个int类型的组数; &a[0]指向的是元素a[0]。 即他们的值相同,但指向的类型不同 */ std::cout<<" 函数"<<MysimpleFunction<<" "<<&MysimpleFunction<<std::endl; Functor<void, TYPELIST_2(int,double)>cmd2(pf); //Functor<void, TYPELIST_2(int,double)>cmd2(&MysimpleFunction); Functor<void, TYPELIST_2(int,double)>cmd3(static_cast<PFun>(MysimpleFunction)); cmd(2,3.4); cmd2(11,3.4455); cmd3(3,4.55); MyClass c; Functor<void,TYPELIST_0()> ff(&c,&MyClass::print); ff(); std::cout<<"End Functor Test.........."<<std::endl; }
相关文章推荐
- 详解C++设计模式编程中策略模式的优缺点及实现
- C++设计模式编程之Flyweight享元模式结构详解
- C++设计模式编程中proxy代理模式的使用实例
- 详解C++设计模式编程中对状态模式的运用
- C++设计模式编程中的观察者模式使用示例
- 详解C++设计模式编程中责任链模式的应用
- 详解C++设计模式编程中对访问者模式的运用
- 详解C++设计模式编程中建造者模式的实现
- C++设计模式编程中Template Method模板方法模式的运用
- C++设计模式::装饰模式or代理模式or面向切片编程(AOP)
- 多线程编程的设计模式 不变模式(一)
- 多线程编程的设计模式 临界区模式(二)
- 多线程编程的设计模式 不变模式(二)
- 高质量C++/C编程指南 -- 第6章 函数设计
- 书评:《ACE程序员指南:网络与系统编程的实用设计模式》
- [导入]小菜编程成长记(十 会修电脑不会修收音机?——聊设计模式原则)
- 也谈单件模式类的设计(C++)
- C#设计模式编程之抽象工厂模式新解
- 多线程编程的设计模式 临界区模式(一)
- [浪子学编程][MS Enterprise Library]ObjectBuilder之设计模式(一):策略模式