函数对象与Lambda

该篇展示两个基本的概念:函数对象和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++书籍。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值