有重载的信号
 

如果信号有重载,比如我们向 Newspaper 类增加一个新的信号:


void newPaper(const QString &name, const QDate &date);

此时如果还是按照前面的写法,编译器会报出一个错误:由于这个函数(注意,信号实际也是一个普通的函数)有重载,因此不能用一个取址操作符获取其地址。回想一下 Qt 4 中的处理。在 Qt 4 中,我们使用 SIGNAL 和 SLOT 两个宏来连接信号槽。如果有一个带有两个参数的信号,像上面那种,那么,我们就可以使用下面的代码:


 

QObject::connect(&newspaper, SIGNAL(newPaper(QString, QDate)),
&reader, SLOT(receiveNewspaper(QString, QDate)));

注意,我们临时增加了一个 receiveNewspaper() 函数的重载,以便支持两个参数的信号。在 Qt 4 中不存在我们所说的错误,因为 Qt 4 的信号槽连接是带有参数的。因此,Qt 能够自己判断究竟是哪一个信号对应了哪一个槽。


对此,我们也给出了一个解决方案,使用一个函数指针来指明到底是哪一个信号:


void (Newspaper:: *newPaperNameDate)(const QString &, const QDate &) = &Newspaper::newPaper;
QObject::connect(&newspaper, newPaperNameDate,
&reader, &Reader::receiveNewspaper);

 


这样,我们使用了函数指针 newspaperNameDate 声明一个带有 QString 和 QDate 两个参数,返回值是 void 的函数,将该函数作为信号,与 Reader::receiveNewspaper() 槽连接起来。这样,我们就回避了之前编译器的错误。归根结底,这个错误是因为函数重载,编译器不知道要取哪一个函数的地址,而我们显式指明一个函数就可以了。

 

如果你觉得这种写法很难看,想像前面一样写成一行,当然也是由解决方法的:


QObject::connect(&newspaper,
(void (Newspaper:: *)(const QString &, const QDate &))&Newspaper::newPaper,
&reader,
&Reader::receiveNewspaper);

 


这是一种换汤不换药的做法:我们只是声明了一个匿名的函数指针,而之前我们的函数指针是有名字的。不过,我们并不推荐这样写,而是希望以下的写法:


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

对比上面两种写法。第一个使用的是 C 风格的强制类型转换。此时,如果你改变了信号的类型,那么你就会有一个潜在的运行时错误。例如,如果我们把 (const QString &, const QDate &) 两个参数修改成 (const QDate &, const QString &),C 风格的强制类型转换就会失败,并且这个错误只能在运行时发现。而第二种则是 C++ 推荐的风格,当参数类型改变时,编译器会检测到这个错误。

参考:​​https://www.qter.org/forum.php?mod=viewthread&tid=637&extra=page%3D3​