编译错误
修改 widget.cpp,添加一行新代码和一个新头文件,如下所示:
#include "widget.h" #include "ui_widget.h" #include <QtTest/QTest> //new header file Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); qsleep(1000); //new code } Widget::~Widget() { delete ui; }
<QtTest/QTest> 是 Qt 单元测试模块的头文件,它里面有一个睡眠函数 void QTest::qSleep(int ms),让当前程序睡眠参数指定的 ms 毫秒。上面示范故意写错了函数名,S 大写变成了小写 s 。
点击运行按钮,或者按下 Ctrl+R 快捷键,就可以看到如下图所示的编译错误:
下面的输出面板自动显示了编译时的错误, qsleep 没有在当前作用域中声明;在源代码编辑器 qsleep(1000) 这一行的行首有红色背景的感叹号,标出了这行有错误发生。
接着我们把睡眠函数改成正确的 qSleep,再次点击运行按钮,或者按下 Ctrl+F5 快捷键,发现还有错误:
还是提示 qSleep 没有声明,但这回给出的错误描述不一样,在问题面板的 “note” 字样一行可以看到提示 “QTest::qSleep”,这次出错是因为 qSleep 函数在名字空间 QTest 里面声明的,如果要用这个函数得加名字空间前缀,或者用 using 语句引入名字空间。我们这里直接给出错的行加名字空间前缀,变成:
QTest::qSleep(1000);
对于编译时错误,常见的就是写错函数名或变量名、类名,没有包含正确的头文件,没有使用正确的名字空间或类前缀等。如果是 Qt 自己的模块或类,直接包含相应的头文件就可以了。
如果是非 Qt 库的头文件,可以在 pro 文件里添加 INCLUDEPATH 变量,比如:
INCLUDEPATH += "E:/mylibs/extra headers"
INCLUDEPATH += "/home/username/extra headers"
上面第一个是 Windows 路径包含,第二个是 Linux/Unix 路径包含。添加包含路径之后,可以在项目源代码里直接包含头文件名:
#include <extra.h>
QtCreator 编辑器支持包含的文件名补全,可自动搜索 Qt 库标准路径和额外包含路径里的头文件。
链接错误
按照上面的说明修改好代码之后,我们就来验证一下吧。再次点击运行按钮,或者按下 Ctrl+R 快捷键,竟然还会有报错信息:
这回也是撞见鬼了,就改了一行代码,还是往正确了改,怎么蹦出十几条错误?最后一条错误描述说明链接器 ld 返回错误了,这是链接目标文件和库文件时出了错误,无法生成最终的可执行程序。问题面板列的十几条错误,就最后倒数第二个是指向 widget.cpp 里的睡眠函数的,报的错误是error: undefined reference to `_imp___ZN5QTest6qSleepEi'
,这是未找到真实的函数引用(定义)的意思,`_imp___ZN5QTest6qSleepEi' 是函数 QTest::qSleep 在编译之后的库文件里的引用名字,链接时找不到引用,通常是没有链接正确的 *.a 库声明文件(Linux 上直接链接到 *.so )。
之前提到 qSleep 是 Qt 单元测试模块里的函数,需要为当前项目添加对应的 Qt 模块,编译链接时 qmake 才会为项目添加正确的头文件目录和链接库文件。上面源代码实际没有问题,出问题的是 HelloWorld.pro 文件。在左边项目视图打开 HelloWorld.pro 文件,编辑如下(注释部分已去掉):
QT += core gui testlib
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = HelloWorld
TEMPLATE = app
SOURCES += /
main.cpp /
widget.cpp
HEADERS += /
widget.h
FORMS += /
widget.ui
上面就是为项目添加了 Qt 模块 testlib ,使用单元测试模块,就应该在 pro 文件里的QT +=
一行里添加 testlib ,然后保存项目文件。
QtCreator 会稍微花些时间重新解析 pro 文件,然后我们点击主菜单菜单“构建 –> 重新构建项目 HelloWorld”,对项目进行重新构建。一般如果修改了 pro 文件,需要手动重新构建项目,避免一些莫名其妙的构建错误(如找不到 WinMain 函数引用)。另外,删除构建目录如 build-HelloWorld-Desktop_Qt_5_9_0_MinGW_32bit-Debug ,然后点击构建或运行按钮,也能实现重新构建项目。如果遇到莫名其妙的构建问题,可以尝试这两种方法。
运行正确编译链接的目标程序,主界面弹出之前会明显感觉到有 1 秒多的迟钝,这是因为我们在主界面构造函数里睡眠了 1000 毫秒,也就是 1 秒。
为 Qt 添加库文件
对于链接时错误,最常遇到的就是本小节里的 undefined reference to **** 链接错误,通常是没有链接到正确的库文件,对于 Qt 自己的库模块,只需要在 pro 文件里QT +=
一行末尾加上对应的模块名字,qmake 就会在编译链接时为项目添加正确的包含路径和链接库文件。
对于非 Qt 模块的库文件,通常是在项目文件 pro 里添加 LIBS 变量行,一般添加规则是:
LIBS += 库文件路径全名
LIBS += -L库文件路径 -l库文件短名
这两种写法都可行。库文件短名是指去掉打头的 lib 和扩展名,只留下中间的,比如 libextra.a 或 libextra.so 都写成 -lextra (Linux 里优先链接动态库 .so,Windows 里不用管这些)。
下面是一些例子:
LIBS += "C:/mylibs/extra libs/extra.lib"
LIBS += "C:/mylibs/extra libs/libextra.a"
LIBS += "-L/home/user/extra libs" -lextra
上面示范的是有空格的路径,必须加双引号才能找到正确位置,如果没空格可以省去双引号。因此不要在库的全路径里出现空格或特殊字符,那纯粹是找麻烦。
示例的第一个 是 VC 库文件用法,第二个是 MinGW 动态链接库引用库 .a 文件或静态库 .a 文件用法,第三个是 Linux/Unix 里的链接库用法,MinGW 也可以采用这种写法。
这些东西在以后的章节里会有些涉及,对于纯 Qt 程序目前不用操心的,这里只是提点一下,等到用的时候再查文档就行了。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/22445.html