函数对象与Lambda

来源:互联网 发布:网络金融平台排名 编辑:程序博客网 时间:2024/05/18 01:01

该篇展示两个基本的概念:函数对象和lambda,其中函数对象是构建Nana的基础。

函数对象(英文上叫function object或functor)就是能像函数那样调用的对象,一般地讲,就是定义了函数调用操作符operator()的类对象。 函数对象是一项非常不错的技术,与普通函数相比更加通用,因为它可以保持调用之后的状态,并且可以对单个对象的初始化和检测,这点通过static的局部变量来实现就很难办到。

class sum{public:sum() : i_(0){}operator int() const volatile{return i_;}//使类对象可以像函数那样调用void operator()(int x) volatile{i_ += x;}private:int i_;};void foo(const std::vector<int>& v){//对所有元素求和std::cout<<std::for_each(v.begin(), v.end(), sum())<<std::endl;}
函数对象保持只有自身的状态,因此可以很方便地使用在并行处理中,并且广泛地使用在程序库的实现中以获得良好的灵活性。

Nana C++ Library大量地使用了函数对象使该框架得以运行。Nana C++ Library引入了一个通用的函数对象类模板:

template<typename Ftype>class functor;

模板参数Ftype被指定为需要代理的函数类型。 类模板functor使Nana摆脱了与各种类型的纠缠。例如:

#include <nana/gui/wvl.hpp>#include <iostream>void foo(){std::system("cls");std::cout<<"foo"<<std::endl;}void foo_with_eventinfo(const nana::gui::eventinfo& ei){std::cout<<"foo_with_eventinfo, mouse pos = ("<<ei.mouse.x<<", "<<ei.mouse.y<<")"<<std::endl;}class click_stat{public:click_stat(): n_(0){}void respond(){std::cout<<"click_stat = "<<++n_<<std::endl;}void respond_ei(const nana::gui::eventinfo& ei){std::cout<<"click_state width eventinfo = "<<n_<<", mouse pos = ("<<ei.mouse.x<<", "<<ei.mouse.y<<")"<<std::endl;}private:int n_;};int main(){using namespace nana::gui;typedef nana::functor<void()> fun_t;typedef nana::functor<void(const eventinfo&)> fun_with_param_t;form fm;click_stat cs;fun_t f(foo);fm.make_event<events::click>(f);f = fun_t(cs, &click_stat::respond);fm.make_event<events::click>(f);fun_with_param_t fp(foo_with_eventinfo);fm.make_event<events::click>(fp);fp = fun_with_param_t(cs, &click_stat::respond_ei);fm.make_event<events::click>(fp);fm.show();exec();}
这里有四种类型的事件处理函数(事件的解释参见文章Hello Nana C++ Library或Programming with Nana C++ Library),并统一地由functor类模板处理。functor类模板提高了灵活度,降低了学习和使用复杂度。

Figure 1.3 方法注册并响应单击事件的各种方法

预定义的函数对象

Nana C++ Library包含了一些不同的预定义的函数对象。用这些函数对象与模板函数一起使用,不但可以增加代码的可读性,而且还能极大提高开发效率。例如,如果一个C++程序想要当点击窗口时关闭该窗口。form.make_event<events::click>(destroy(form));在使用这些函数对象前,请包含<nana/gui/functional.hpp>

class destroy{public:destroy(nana::gui::window wd);void operator()() const;};

销毁窗口。


class hide{public:hide(nana::gui::window wd);void operator()() const;};
隐藏窗口。


class show{public:show(nana::gui::window wd);void operator()() const;};
显示窗口。


Lambda 表达式

Lambda表达式是一个制定函数对象的机制,是最近引入C++的新特性,主要用途为某些函数制定简单的操作。例如:

#include <nana/gui/wvl.hpp>#include <iostream>int main(){using namespace nana::gui;form fm;fm.make_event<events::click>([]{ std::cout<<"form is clicked"<<std::endl; });fm.show();exec();}

这实参 []{ std::cout<<"form is clicked"<<std::endl; } 在C++(11)语言中是一个"Lambda"(或者 "Lambda函数" 或者 "Lambda 表达式")。Lambda以简单的中括号[]开始,和复合语句块{}来定义一个函数体,实际上,Lambda定义了一个匿名的函数对象,因此可以用函数调用语法来调用这个Lambda,例如

[]{ std::cout<<"form is clicked"<<std::endl; }();

Lambda的作用是创建一个匿名的函数对象,因此也可以为它指定参数列表。例如:

fm.make_event<events::click>([](const eventinfo& ei){std::cout<<"mouse pos=("<<ei.mouse.x<<", "<<ei.mouse.y<<")"<<std::endl;});

Lambda-declarator()用法于参数列表一样。现在我们暂停对Lambda的介绍,更多的细节请参考C++书籍。

原创粉丝点击