您的位置:首页 > 编程语言 > C语言/C++

Modern C++ Design 笔记 第五章 Generalized Functors

2008-12-03 14:11 309 查看
说到Funtor呢,应该是STL中比较普遍使用的一个东西。大致的意思就是把一个类对象像函数一样的使用,当然这个类需要重载()操作符。因为他比较像函数,所以得了一个Funtor的名字,至于翻译好像主流的叫函数子??有点搞不清状况。
还是看一个最简单的Funtor的例子吧

// test functor class

template<class T> class plus

{

public:

void operator() (T& aa)

{

aa += 10;

}

};

// test function

template<class T> void c_print( const T& value)

{

std::cout<<value<<std::endl;

}

int main (void)

{

std::vector<int> v;

v.push_back(10);

v.push_back(11);

v.push_back(12);

for_each(v.begin(), v.end(), plus<int>());

for_each(v.begin(), v.end(), c_print<int>);

}
这个可以看到的是Functor完成了函数一样的工作,但是同时也提供了一些便利的地方,代码符合C++的风格倒是真的。如果能想到的好处可能就是实际上模板函数和模板类的不同,比如我即使用函数,在有的情况的还是不罩的。我没有办法给一个模板函数偏特化,这种情况下当然类就要有优势了。但是没有什么绝对的。另外有些所谓调用性能上的提升,我不敢苟同。也同时觉得现代的应用程序的瓶颈定不在于此。我做了些比如std::sort中的less than的一些自己的实现,并没有发现所谓的雪崩效应,那个comparer functor和compare函数没有什么明显的性能上的差异。这时候的数量级已经到了100000。
说的比较远了,还是回过来继续说这里的Functor的实现,这里的Functor的引出呢是源自与Command这种设计模式。这种模式有效的降低了invoker和receiver之间的联系。这种模式有图为证:



而我们的Functor则成了实现这个Command或者说ConcreteCommand的利器。而且这个书层层递进的解说让人欲罢不能啊:)
首先看看最基本的实现:

// Functor with any number and types of arguments

template <typename ResultType, class TList>

class Functor

{

...

};
可以看见的是这是第一步,就是了解模板的类型参数有哪些,通过字面意思可以理解的是明显的就是返回值和参数,返回值当然就是某个特定的类型ResultType而这个参数就又一次依赖了TypeList。有了这些定义呢,我们已经可以想象到完成之后的调用语句的形状了:) 类似于 Functor<double, TYPELIST_2(int, double)> myFunctor;
当然啦,为了多态等因素的考虑,实际的实现肯定不是这么简单,实际上是吧operate()的调用分发了一个叫FunctorImpl的类来完成的,这个类的定义基本上是这个样子的。

template <typename R>

class FunctorImpl<R, NullType>

{

public:

virtual R operator()() = 0;

virtual FunctorImpl* Clone() const = 0;

virtual ~FunctorImpl() {}

};
可以看到的是这里的operator()都是以虚函数的形式存在的。同时在Functor类里面的FunctorImpl我们引用了std::auto_prt这个智能指针:

template <typename R, class TList>

class Functor

{

public:

...

Functor& operator=(const Functor&);

explicit Functor(std::auto_ptr<Impl> spImpl);

...

private:

// Handy type definition for the body type

typedef FunctorImpl<R, TList> Impl;

std::auto_ptr<Impl> spImpl_;

};
所以这个具体operator的实现呢应该就大致如下,每个functor的()调用实际上都是调用spImpl_对应的()操作符。

R operator()()

{

return (*spImpl_)();

}

R operator()(Parm1 p1)

{

return (*spImpl_)(p1);

}
其实到这里,基本上我们一个Functor template就完成的七七八八了。当然还有比这个更复杂的东西, 比如说传入的Functor参数不是一个类,而直接是一个函数,我们也应该可以完成调用,就像STL的那些函数一样。由此引来的问题还有如果是一个成员函数是不是也可以捏?好多的为什么:) 这个我们就偷懒一把,浅尝辄止了。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: