需求
qt 在使用 connect
连接时,有些时候因为类型匹配的问题,会报错:
QPushButton * controller_button_[APP_NUM_OF_CONTROLLER];
QSignalMapper * signalMapper_;
signalMapper_ = new QSignalMapper(this);
for (int i = 0; i < APP_NUM_OF_CONTROLLER; i++) {
controller_button_[i] = new QPushButton(this);
connect(controller_button_[i], &QPushButton::clicked, signalMapper_, &QSignalMapper::map);
signalMapper_->setMapping(controller_button_[i], i);
}
connect(signalMapper_, &QSignalMapper::mapped, this, &MainWindow::ClickDetail);
mainwindow.cpp:173:9: error: no matching member function for call to 'connect'
qobject.h:222:36: note: candidate function not viable: no known conversion from 'void (QAbstractButton::*)(bool) __attribute__((thiscall))' to 'const char *' for 2nd argument
qobject.h:225:36: note: candidate function not viable: no known conversion from 'void (QAbstractButton::*)(bool) __attribute__((thiscall))' to 'const QMetaMethod' for 2nd argument
qobject.h:481:41: note: candidate function not viable: no known conversion from 'void (QAbstractButton::*)(bool) __attribute__((thiscall))' to 'const char *' for 2nd argument
qobject.h:242:43: note: candidate template ignored: couldn't infer template argument 'Func2'
qobject.h:283:13: note: candidate template ignored: couldn't infer template argument 'Func2'
qobject.h:322:13: note: candidate template ignored: couldn't infer template argument 'Func2'
qobject.h:274:13: note: candidate function template not viable: requires 3 arguments, but 4 were provided
qobject.h:314:13: note: candidate function template not viable: requires 3 arguments, but 4 were provided
虽然可以使用 SIGNAL()
, SLOT()
这样,qt4 旧的 style 来写,但是还是希望能够使用 qt5 新 style 写。
connect(controller_button_[i], SIGNAL(clicked()), signalMapper_, SLOT(map()));
connect(signalMapper_, SIGNAL(mapped(int)), this, SLOT(ClickDetail(int)));
解决
其实报错的时候,已经说的很清楚了,就是类型的问题。首先需要核对信号函数的类型和槽函数的类型,然后才能决定后面怎么来写。
void clicked(bool checked = false);
void map();
void map(QObject *sender);
void mapped(int);
void mapped(const QString &);
void mapped(QWidget *);
void mapped(QObject *);
void MainWindow::ClickDetail(int id);
信号和槽能匹配类型
可以看到上面的 mapped
其中一种是可以和 ClickDetial
类型匹配的,所以我们只需要明确指出具体是哪种类型即可。 C++11
只能使用 QOverload
,
C++14
还可以使用 qOverload
.
// c++11
connect(signalMapper_, QOverload<int>::of(&QSignalMapper::mapped), this, &MainWindow::ClickDetail);
// c++14
connect(signalMapper_, qOverload<int>(&QSignalMapper::mapped), this, &MainWindow::ClickDetail);
信号和槽不能匹配类型
clicked
和 map
没有一个能完全匹配,我们只能想其他方法,最简单的就是套壳再包装一层。我们可以使用 Lambda
表达式来达成目的。
connect(controller_button_[i], &QPushButton::clicked, signalMapper_, [=]() {signalMapper_->map();});
参考
no matching member function for call to ‘connect’ - simple example why doesn’t this work??