众所周知,Qt中的信号与相应的槽函数,它们的参数列表和返回值需要完全对应。信号是没有返回值的,所以槽函数也一定没有返回值。在使用Qt的时候,可以使用重载的方法来定义信号和槽函数的多个版本,此时就会有一些冲突需要引起我们注意。
// 信号
signals:
void my_sgn();
void my_sgn(int, char*);
// 对应的槽函数
// 无参数版本槽函数
void MyWidget::mySlotFun()
{
qDebug("no arguments");
}
// 有参数版本槽函数
void MyWidget::mySlotFun(int num, char *str)
{
qDebug() << num << str << endl;
}
在使用connect关联重载多个版本的信号与槽函数时,如果不加以区别,编译器将无法确定该使用哪一个版本的槽函数,产生二义性,这是编译器不允许的。
// 这里的my_sgn时指mySlotFun()还是mySlotFun(int, char*)呢?
connect(&btn, &SubWidget::my_sgn, this, &MyWidget::mySlotFun);
方法一
为了解决这个问题,可以利用函数指针显式地指出信号版本(注意是指向信号,函数指针同时也要指明作用域),具体用法如下:
// 无参数版本
void (SubWidget::*pt_no_arg)() = &SubWidget::my_sgn;
connect(&btn, pt_no_arg, this, &MyWidget::mySlotFun);
//有参数版本
void (SubWidget::*ptr_have_arg)(int, char*) = &SubWidget::mySlotFun;
connect(&btn, ptr_have_arg, this, &MyWidget::mySlotFun);
如此一来,编译器就能知道信号的使用的重载版本,也就能调用相应版本的槽函数了。
方法二
Qt 4以上的版本可以使用宏SIGNAL()和SLOT()来解决这个问题,使用这种方法,注意在声明槽函数时要加上修饰符slots
class MyWidget{
...
public slots:
mySlotFun();
mySlotFun(int num, char *str);
...
};
class SubWidget{
...
signals:
void my_sgn();
void my_sgn(int, char*);
};
// 无参版本
connect(&btn, SIGNAL(my_sgn()), this, SLOT(mySlotFun()));
// 有参版本
connect(&btn, SIGNAL(my_sgn(int, char*)), this, SLOT(mySlotFun(int, char*)));
这一方法有一点缺陷,就是即使你写错了函数名字,在编译的时候也不会报错,而会在运行时才报错(因为该宏是将函数转换为符合C++函数名规格的字符串),而使用方法一不会有这种问题。