番茄工具rename引起的bug - 建议使用新式Qt connect 写法

测试《Qt Creator快速入门 第3版》书中代码测试TCP发送数据引起的问题

问题

今天拿《Qt Creator快速入门 第3版》书中代码测试TCP发送数据,代码位于src/18/18-9/tcpclient下,Client类构造函数如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Client::Client(QWidget *parent) :
QDialog(parent),
ui(new Ui::Client)
{
ui->setupUi(this);

payloadSize = 64*1024; // 64KB
totalBytes = 0;
bytesWritten = 0;
bytesToWrite = 0;
tcpClient = new QTcpSocket(this);

// 当连接服务器成功时,发出connected()信号,开始传送文件
connect(tcpClient, SIGNAL(connected()), this, SLOT(startTransfer()));
connect(tcpClient, SIGNAL(bytesWritten(qint64)),
this, SLOT(updateClientProgress(qint64)));
connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayError(QAbstractSocket::SocketError)));
ui->sendButton->setEnabled(false);
}

强迫症驱使将代码用VassistX工具将类成员变量改名,改完后的代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Client::Client(QWidget *parent) :
QDialog(parent),
ui(new Ui::Client)
{
ui->setupUi(this);

payloadSize_ = 64*1024; // 64KB
totalBytes_ = 0;
bytesWritten_ = 0;
bytesToWrite_ = 0;
tcpClient_ = new QTcpSocket(this);

// 当连接服务器成功时,发出connected()信号,开始传送文件
connect(tcpClient_, SIGNAL(connected()), this, SLOT(startTransfer()));
connect(tcpClient_, SIGNAL(bytesWritten_(qint64)),
this, SLOT(updateClientProgress(qint64)));
connect(tcpClient_, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayError(QAbstractSocket::SocketError)));
ui->sendButton->setEnabled(false);
}

编译通过,但是却无法发送数据,又是检查网络又是检查数据折腾半天,还是没找到问题。最后发现是我用VassistX工具改变量名时,由于变量名和QTcpSocket::bytesWritten信号名相同,导致SIGNAL宏括号中的bytesWritten_(qint64)信号名(就是个字符串)也被改名了。

1
2
connect(tcpClient_, SIGNAL(bytesWritten_(qint64)),
this, SLOT(updateClientProgress(qint64)));

关键是编译时没有任何错误提示,所以强烈推荐在Qt5中使用新式的connect写法:

1
connect(tcpClient_, &QTcpSocket::bytesWritten, this, &Client::updateClientProgress);

1
2
connect(tcpClient_, &QTcpSocket::bytesWritten, [=](qint64 numBytes) {
});
  1. 通过VassistX工具改名不会改上面代码中的&QTcpSocket::bytesWritten;
  2. 就算改了,或是不小心自己改了,编译器直接会给出如下错误提示错误 C2039 “bytesWritten_”: 不是“QTcpSocket”的成员
  3. 不仅是信号名,SIGNAL(bytesWritten(qint64))这种写法,参数类型、顺序写错都不能写错,否则也会出现运行期错误,编译器改错总比运行期去排查错误要简单的多。

总结

  1. 除非要兼容Qt4,否则尽量使用新式的connect写法。
  2. 变量、函数命名尽量不要重复,个人感觉Qt开发变量名更推荐使用bytes_written这种写法,以减少与Qt自带函数、变量重名的概率。
  3. 能在编译器解决的问题,不要拖到运行期。比如:新式枚举enum class传参比直接传intQString更容易在编译器发现问题。

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!