c++ 泛型 程式設計 之 Functor 設計模式
完整程式碼見:
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++ 泛型程式設計 之 TypeListsC++泛型程式設計
- 十、GO程式設計模式 : 泛型程式設計Go程式設計設計模式泛型
- c++ 泛型程式設計 之 自動生成程式碼C++泛型程式設計
- 泛型程式設計泛型程式設計
- C++ primer 模板與泛型程式設計C++泛型程式設計
- java 泛型程式設計Java泛型程式設計
- JavaScript設計模式之建立型設計模式JavaScript設計模式
- C++ 泛型程式設計基礎:模板通識C++泛型程式設計
- JavaScript設計模式之結構型設計模式JavaScript設計模式
- 物件導向程式設計和`GP`泛型程式設計物件程式設計泛型
- 泛型程式設計詳解(一)泛型程式設計
- 泛型程式設計與 OI——modint泛型程式設計
- C++ 設計模式之命令模式C++設計模式
- C++設計模式之代理模式C++設計模式
- 02. 程式設計核心內功心法之泛型程式設計泛型
- C++設計模式建立型工廠模式C++設計模式
- 泛型程式設計在非C++語言中的實現之探討 (轉)泛型程式設計C++
- .NET泛型程式設計簡介 (轉)泛型程式設計
- C++設計模式之Proxy模式(代理模式)C++設計模式
- C++ STL與泛型程式設計-第一篇 (Boolan)C++泛型程式設計
- C++ 簡單實現陣列類泛型程式設計示例C++陣列泛型程式設計
- PHP設計模式—建立型設計模式PHP設計模式
- C++設計模式::裝飾模式or代理模式or面向切片程式設計(AOP)C++設計模式程式設計
- 設計模式之代理模式(結構型)設計模式
- GO語言泛型程式設計實踐Go泛型程式設計
- Java程式設計之設計模式之工廠方法模式全解Java程式設計設計模式
- JavaScript設計模式之物件導向程式設計JavaScript設計模式物件程式設計
- 設計模式(一)建立型之單例模式設計模式單例
- 設計模式之單例設計模式設計模式單例
- 【C++ 泛型程式設計01:模板】函式模板與類别範本C++泛型程式設計函式
- 在C語言中實現泛型程式設計C語言泛型程式設計
- C語言如何實現泛型程式設計?C語言泛型程式設計
- Swift使用協議加泛型程式設計(一)Swift協議泛型程式設計
- 好程式設計師分享java設計模式之享元模式程式設計師Java設計模式
- 泛型最佳實踐:Go泛型設計者教你如何用泛型泛型Go
- 好程式設計師Java教程分享Java難點解析之泛型程式設計師Java泛型
- QML之C++混合程式設計C++程式設計
- 設計模式-建立型設計模式