Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在不存储连接的情况下断开lambda函数_C++_Qt_C++11_Lambda - Fatal编程技术网

C++ 如何在不存储连接的情况下断开lambda函数

C++ 如何在不存储连接的情况下断开lambda函数,c++,qt,c++11,lambda,C++,Qt,C++11,Lambda,有没有办法在不存储连接对象的情况下断开与lambda函数的连接 我知道如果我存储从connect函数返回的QMetaObject::Connection,这是可能的,但我并不真的想这样做,因为会有很多。我主要连接lambda函数以避免创建一堆一次性的方法和对象,如果我需要做所有的簿记工作,那么slot会更可取。这是撰写本文的唯一方法: QMetaObject::Connection connection = QObject::connect(psender, &MyClass::

有没有办法在不存储连接对象的情况下断开与lambda函数的连接


我知道如果我存储从connect函数返回的
QMetaObject::Connection
,这是可能的,但我并不真的想这样做,因为会有很多。我主要连接lambda函数以避免创建一堆一次性的方法和对象,如果我需要做所有的簿记工作,那么
slot
会更可取。

这是撰写本文的唯一方法:

QMetaObject::Connection connection =
    QObject::connect(psender, &MyClass::mySignal, [] () { /* Do the work */ });
QObject::disconnect(connection);
有关断开连接方法的参考,请参阅

bool QObject::disconnect(const QMetaObject::Connection&Connection)[静态]

断开连接

如果连接无效或已断开连接,则不执行任何操作并返回false


在一天结束时,您仍然会使用插槽进行簿记,只是如果您确实需要本地化,lambda似乎更本地化,因此我认为这取决于您的个人喜好。

以下是隐藏簿记问题的两种方法

首先,我们维护一个
std::vector
,它在销毁时将我们与源断开连接:

typedef std::shared_ptr<void> listen_token;

struct disconnecter {
  QMetaObject::Connection conn;
  disconnecter(   QMetaObject::Connection&& c ):conn(std::move(c)) {}
  ~disconnecter() { QObject::disconnect(conn); }
};

template<class F, class T, class M>
listen_token QtConnect( T* source, M* method, F&& f ) {
  return std::make_shared<disconnecter>(
    QObject::connect( source, method, std::forward<F>(f));
  );
}

typedef std::vector<listen_token> connections;
这里我们
one_shot\u connect(bob,&bob::mySignal,[](QString str){std::cout假设一个连接:

QObject::connect(senderInstance, &Sender::mySignal, this, []() {
    // implement slot as a lambda
});
然后,您可以通过以下方式轻松断开连接:

QObject::disconnect(senderInstance, &Sender::mySignal, this, nullptr);

这将断开
发送方::mySignal
的所有
插槽;但是,通常只有一个这样的插槽,因此最终结果是断开操作简单且没有副作用。

您可以使用虚拟对象:

QObject *obj = new QObject(this);
QObject::connect(m_sock, &QLocalSocket::readyRead, obj, [this](){
   obj->deleteLater();

当obj被破坏时,连接被断开,因为你在连接上传递了obj。

你会怎么想,如果不再次存储某种状态,你会怎么做?我无法想象,这就是我问社区的原因。似乎如果没有办法,lambda语法对于断开连接的情况不是很有用s必需。为什么在这里使用共享的而不是唯一的\u ptr?@povman
std::function
和概念调用的大多数类型擦除也需要复制(在上面的第二种情况下),并且
unique
将阻止复制。在第一种情况下,
unique
可以工作,但需要更多的键入(以存储显式销毁程序),或更少的抽象(在令牌中存储显式目标,而不是
void
)。和其他侦听器-观察者系统需要侦听器令牌中的不同数据,因此我习惯于使用
共享\u ptr
。好主意,但是模板参数推断错误,我不知道原因。第一种方法中的代码是否编译(使用bob或其他示例)?我得到一个错误C2784:'listen_-token QtConnect(T,M*,F&)':当我尝试将其与QSerialPort一起使用时,无法从'void('cdecl QIODevice::)(qint64)'(void)推断'M*'的模板参数。我按如下方式调用QtConnect(mPort.get(),&QSerialPort::bytesswrited,[&](qint64字节){…};关于如何修复此问题,您有什么想法吗?传统的connect可以正常工作连接(mPort.get(),&QSerialPort::bytesWrite,this,&MainWindow::processTx);我无法用g++7.3和c++17编译这个。有人成功了吗?@eudoxos哪一个?我现在既没有在线Qt编译器,也没有离线Qt编译器,但我仔细阅读了第一部分,没有发现任何明显的错误。我的意思是,我错过了第二段到最后一段中的
Bob::mySignal
之前的
&
?我在上面做了很多假设,没有方法的重载和签名等等。谢谢David!我同意这可能涵盖了60-70%的场景。它非常有效,谢谢
myObject->disconnect(SIGNAL(mySignal());
@NicolasHolthaus还与
QObject
相关的所有东西都在
~QObject()中被断开
,其中涵盖了大量的own@caleth当然,这只适用于您不想像此解决方案那样破坏已连接对象的情况,因为它更简单、更干净。只需捕获obj即可进行调用。我得到
QObject:无法为处于不同线程中的父线程创建子线程。
run-time…或使用
作为虚拟对象,如果它是
QObject
QObject::disconnect(senderInstance, &Sender::mySignal, this, nullptr);
QObject *obj = new QObject(this);
QObject::connect(m_sock, &QLocalSocket::readyRead, obj, [this](){
   obj->deleteLater();