Lambda表达式以及在QT5信号槽函数connect中的应用

部分内容来自:https://blog.csdn.net/zhouchunyue/article/details/79753235

Lambda表达式以及在QT5信号槽函数connect中的应用

示例
注:两种Lambda连接方法都适用于当连接的信号为重载信号时。

void (QSignalMapper::*mapped)(int) = &QSignalMapper::mapped;
connect(m_signalMapper, mapped, [=](int nControlIndex {
	controlButtonClicked(nControlIndex);
});
connect(m_signalMapper, static_cast<void(QSignalMapper::*)(int)>(&QSignalMapper::mapped), [=](int nControlIndex {
	controlButtonClicked(nControlIndex);
});
static_cast<void(QSignalMapper::*)(int)>(&QSignalMapper::mapped)
上面这句是一个静态转换 static_cast<>()
  • QSignalMapper:: * 是类指针
  • int 函数参数
  • &QSignalMapper::mapped 函数地址

Lambda基本语法

简单来说,Lambda函数也就是一个匿名函数,类似于object -c里面的一个代码块block语法,能够在调用语句后面马上列出要执行的代码,不需要预先声明。它的语法定义如下:

[capture](parameters) mutable->return-type { statement } 
  1. [capture]:捕捉列表。捕捉列表总是出现在Lambda函数的开始处。实际上,[]这对方括号被称为Lambda表达式引入符。捕捉列表能够捕捉上下文中的变量以供Lambda函数使用;

  2. (parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号“()”一起省略;

  3. mutable:mutable修饰符。默认情况下,Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空);

  4. ->return-type:返回类型。用追踪返回类型形式声明函数的返回类型。我们可以在不需要返回值的时候也可以连同符号”->”一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导;

  5. {statement}:函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

与普通函数最大的区别是,除了可以使用参数以外,Lambda函数还可以通过捕获列表访问一些上下文中的数据。具体地,捕捉列表描述了上下文中哪些数据可以被Lambda使用,以及使用方式(以值传递的方式或引用传递的方式)。语法上,在“[]”包括起来的是捕捉列表,捕捉列表由多个捕捉项组成,并以逗号分隔。捕捉列表有以下几种形式:

  1. [var]表示值传递方式捕捉变量var;
  2. [=]表示值传递方式捕捉所有父作用域的变量(包括this);
  3. [&var]表示引用传递捕捉变量var;
  4. [&]表示引用传递方式捕捉所有父作用域的变量(包括this);
  5. [this]表示值传递方式捕捉当前的this指针。

上面提到了一个父作用域,也就是包含Lambda函数的语句块,说通俗点就是包含Lambda表达式的那段代码块。上面的捕捉列表还可以进行组合,例如:

  1. [=, &a, &b]表示以引用传递的方式捕捉变量a和b,以值传递方式捕捉其它所有变量;
  2. [&, a, this]表示以值传递的方式捕捉变量a和this,引用传递方式捕捉其它所有变量。

不过值得注意的是,捕捉列表不允许变量重复传递。下面一些例子就是典型的重复,会导致编译时期的错误。例如:

  1. [=, a]这里已经以值传递方式捕捉了所有变量,但是重复捕捉a了,会报错的;

  2. [&, &this]这里&已经以引用传递方式捕捉了所有变量,再捕捉this也是一种重复。

在QT5 connect函数中的应用

我们都知道Qt5中允许信号和槽的参数数目不一致:槽函数的参数数目可以比信号的参数少。这是因为,我们信号的参数实际是作为一种返回值。正如普通的函数调用一样,我们可以选择忽略函数返回值,但是不能使用一个并不存在的返回值。如果槽函数的参数数目比信号的多,在槽函数中就使用到这些参数的时候,实际这些参数并不存在(因为信号的参数比槽的少,因此并没有传过来),函数就会报错。

然而,有一种情况,槽函数的参数可以比信号的多,那就是槽函数的参数带有默认值。比如,我们的Newspaper和Reader有下面的代码:

// Newspaper
signals:
    void new Paper(const QString& name);
// Reader
    void receiveNewspaper(const QString& name, const QDate& date=QDate::currentDate());

虽然Reader::receiveNewspaper()的参数数目比Newspaper::newPaper()多,但是由于Reader::receiveNewspaper()后面一个参数带有默认值,
所以该参数不是必须提供的。但是,如果你按照下面的写法,比如如下的代码:

connect(&newspaper,
        static_cast<void (Newspaper::*)(const QString&)>(&Newspaper::newPaper),
        &reader,
        static_cast<void (Reader::*)(const QString&, const QDate& = QDate::curentDate())>(&Reader::receiveNewspper));

你会得到一个断言错误:The slot requires more arguments than the signal provides.

我们不能在函数指针中使用函数参数的默认值。这是 C++ 语言的限制:参数默认值只能使用在直接地函数调用中。当使用函数指针取其地址的时候,默认参数是不可见的!
当然,此时你可以选择 Qt 4 的连接语法。如果你还是想使用 Qt 5 的新语法,目前的办法只有一个:Lambda 表达式。
于是,我们的代码就变成了:

connect(&newspaper,
        static_cast<void(Newspaper::*)(const QString&)>(&Newspaper::newPaper), 
        [=](const QString& name) { /* Your code here. */ });

此时信号发出后没有接收者,只执行Lambda表达式这个匿名函数里的操作。这也是connect函数的一个重载,最后一个参数是 Functor 类型。
这个类型可以接受 static 函数、全局函数以及 Lambda 表达式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值