Qt编译和链接错误
为了演示 Qt Creator 的报错信息,我们刻意制造一个小 Bug。依然使用《Qt Creator使用教程(简明版)》一节中创建的项目和代码,双击 HelloWorld.pro,或者在 Qt Creator 主菜单中选择“文件 --> 打开文件或项目”,或者按下 Ctrl+O 快捷键都可以打开 HelloWorld 项目。
点击运行按钮,或者按下 Ctrl+R 快捷键,就可以看到如下图所示的编译错误:
下面的输出面板自动显示了编译时的错误, qsleep 没有在当前作用域中声明;在源代码编辑器 qsleep(1000) 这一行的行首有红色背景的感叹号,标出了这行有错误发生。
接着我们把睡眠函数改成正确的 qSleep,再次点击运行按钮,或者按下 Ctrl+F5 快捷键,发现还有错误:
还是提示 qSleep 没有声明,但这回给出的错误描述不一样,在问题面板的 “note” 字样一行可以看到提示 “QTest::qSleep”,这次出错是因为 qSleep 函数在名字空间 QTest 里面声明的,如果要用这个函数得加名字空间前缀,或者用 using 语句引入名字空间。我们这里直接给出错的行加名字空间前缀,变成:
如果是非 Qt 库的头文件,可以在 pro 文件里添加 INCLUDEPATH 变量,比如:
这回也是撞见鬼了,就改了一行代码,还是往正确了改,怎么蹦出十几条错误?最后一条错误描述说明链接器 ld 返回错误了,这是链接目标文件和库文件时出了错误,无法生成最终的可执行程序。问题面板列的十几条错误,就最后倒数第二个是指向 widget.cpp 里的睡眠函数的,报的错误是
之前提到 qSleep 是 Qt 单元测试模块里的函数,需要为当前项目添加对应的 Qt 模块,编译链接时 qmake 才会为项目添加正确的头文件目录和链接库文件。上面源代码实际没有问题,出问题的是 HelloWorld.pro 文件。在左边项目视图打开 HelloWorld.pro 文件,编辑如下(注释部分已去掉):
QtCreator 会稍微花些时间重新解析 pro 文件,然后我们点击主菜单菜单“构建 --> 重新构建项目 HelloWorld”,对项目进行重新构建。一般如果修改了 pro 文件,需要手动重新构建项目,避免一些莫名其妙的构建错误(如找不到 WinMain 函数引用)。另外,删除构建目录如 build-HelloWorld-Desktop_Qt_5_9_0_MinGW_32bit-Debug ,然后点击构建或运行按钮,也能实现重新构建项目。如果遇到莫名其妙的构建问题,可以尝试这两种方法。
运行正确编译链接的目标程序,主界面弹出之前会明显感觉到有 1 秒多的迟钝,这是因为我们在主界面构造函数里睡眠了 1000 毫秒,也就是 1 秒。
对于非 Qt 模块的库文件,通常是在项目文件 pro 里添加 LIBS 变量行,一般添加规则是:
下面是一些例子:
示例的第一个 是 VC 库文件用法,第二个是 MinGW 动态链接库引用库 .a 文件或静态库 .a 文件用法,第三个是 Linux/Unix 里的链接库用法,MinGW 也可以采用这种写法。
这些东西在以后的章节里会有些涉及,对于纯 Qt 程序目前不用操心的,这里只是提点一下,等到用的时候再查文档就行了。
编译错误
修改 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"
#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 ,然后保存项目文件。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库文件短名
下面是一些例子:
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 程序目前不用操心的,这里只是提点一下,等到用的时候再查文档就行了。
所有教程
- socket
- Python基础教程
- C#教程
- MySQL函数
- MySQL
- C语言入门
- C语言专题
- C语言编译器
- C语言编程实例
- GCC编译器
- 数据结构
- C语言项目案例
- C++教程
- OpenCV
- Qt教程
- Unity 3D教程
- UE4
- STL
- Redis
- Android教程
- JavaScript
- PHP
- Mybatis
- Spring Cloud
- Maven
- vi命令
- Spring Boot
- Spring MVC
- Hibernate
- Linux
- Linux命令
- Shell脚本
- Java教程
- 设计模式
- Spring
- Servlet
- Struts2
- Java Swing
- JSP教程
- CSS教程
- TensorFlow
- 区块链
- Go语言教程
- Docker
- 编程笔记
- 资源下载
- 关于我们
- 汇编语言
- 大数据
- 云计算
- VIP视频