查看文章 |
Qt 是 C++ 的库,Qt在ansi C++ 的基础上进行了一点扩展。 但国内似乎比较浮躁,学Qt的很多连基本的C++如何编译似乎都不太清楚。本文舍弃IDE或qmake、cmake等工具的束缚,尝试通过几个例子,一步一步从标准 C++ 的编译过渡到 Qt 的编译。 本文涉及的都是最基本的东西,或许可以说,只要你用C++ Qt,不管是通过哪种工具(qmake、cmake、boost.build、qtcreator、vs2008、Eclipse、...),本文的内容都是需要理解的(尽管真正写程序时,我们都不会直接用C++编译器来编译Qt程序)。 如果你对命令行比较恐惧,或许愿意先看看我原来整理的这个 http://wiki.ubuntu.org.cn/Gcchowto 例子一:简单的控制台程序一个很简单的例子,没用到Qt扩展:(也就是说,这是一个普通的C++程序) #include <QtCore/QCoreApplication> 我们都知道,编译一个C++的程序,无非是 编译预处理,编译、链接
g++简单一行命令,即可生成 main.exe (linux下,则生成可执行程序 main) g++ main.cpp -DQT_CORE_LIB -Ie:\Qt\4.7.0\include -o main -Le:\Qt\4.7.0\lib -lQtCore4 单行命令,很简单:
cl简单一行命令,即可生成 main.exe cl main.cpp -ID:/Qt/4.7.0/include -DQT_CORE_LIB -Femain -link -LIBPATH:D:/Qt/4.7.0/lib QtCore4.lib 依然很简单
例子二:简单的GUI程序这次稍微复杂一点,不是单一的控制台程序,而是一个简单的GUI程序
#include <QtGui/QApplication>
#include <QtGui/QWidget>
#include "widget.h" 同样,这个程序未使用Qt的扩展,直接用C++的编译器编译: g++
g++ main.cpp widget.cpp -DQT_CORE_LIB -DQT_GUI_LIB -Ie:\Qt\4.7.0-beta2\include -o main -Le:\Qt\4.7.0-beta2\lib -lQtCore4 -lQtGui4 因为我们使用了QtGui模块,所以和前面相比:
注意: Windows下 如果在非windows平台下,这条命令就可以了。但windows下,你知道的:分console和windows两个链接子系统,而且入口函数分 main 和 WinMain 。 这条命令,编译出的 main.exe 会弹出控制台。要想不要控制台,则使用下面的命令: g++ main.cpp widget.cpp -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NEEDS_QMAIN -Ie:\Qt\4.7.0-beta2\include -o main -Le:\Qt\4.7.0-beta2\lib -lQtCore4 -lQtGui4 -lqtmain -Wl,-subsystem,windows 多了两个选项:
cl同windows下的g++基本一样,带控制台: cl main.cpp widget.cpp -ID:/Qt/4.7.0/include -DQT_CORE_LIB -DQT_GUI_LIB -Femain -link -LIBPATH:D:/Qt/4.7.0/lib QtCore4.lib QtGui4.lib 不带控制台: cl main.cpp widget.cpp -ID:/Qt/4.7.0/include -DQT_CORE_LIB -DQT_GUI_LIB -Femain /MD -link -LIBPATH:D:/Qt/4.7.0/lib -subsystem:windows qtmain.lib QtCore4.lib QtGui4.lib 分析同上:指定链接子系统,启用WinMain入口函数 多文件的程序如何管理直接调用编译器有什么坏处呢?
改变这种状况的办法,传统的就是写 Makefile,然后编译时只需要输入 make 就行了,他会判断哪些文件被改动需要重新编译。 另外就是VS等一些IDE自己提供的功能。下面简单看一下本例子对应makefile文件: mingw32-make的Makefile文件 CPPFLAGS = -DQT_CORE_LIB -DQT_GUI_LIB -Ie:\Qt\4.7.0\include nmake的Makefile文件 CPPFLAGS = -ID:/Qt/4.7.0/include -DQT_CORE_LIB -DQT_GUI_LIB -MD 对此不做介绍,因为Makefile编写也是一门学问。相当难写,所有才有qmake、cmake这些工具来帮我们生成Makefile文件 例子三:引入mocQt 对 C++ 的扩展主要是3个方面:
这3者之中,元对象系统最复杂,也是 Qt 程序中重要的。其他两个你都可以不要,唯独这个不要就有点不像话了(没它还叫Qt程序么?像我们前面写的,只不过是普通的C++程序) 废话少说,看例子:(修改前面的widget.h,加入Q_OBJECT) #include <QtGui/QWidget> 如何编译这个程序呢?例子二中的命令还能用吗?不妨试试:
来自 g++ 的问候: main.o:main.cpp:(.text$_ZN6WidgetD1Ev[Widget::~Widget()]+0xb): undefined reference to `vtable for Widget' 来自 cl 的问候: widget.obj : error LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __thiscall Widget::metaObject(void)const " (?metaObject@Widget@@UBEPBUQMetaObject@@XZ) 发生了什么?添加一个宏后,发生了什么?我们看看编译器将宏展开后是什么样子的: #include <QtGui/QWidget> 一下子多出来这么多函数,而且还没有函数体,不出错才怪。如何生成函数体呢?这正是moc所做的: moc widget.h -o moc_widget.cpp 这样一来,这些函数都在 moc_widget.cpp 被实现了,只要我们将该文件一块编译链接就行了 对g++来说,在例子二的基础上,直接添加一个 moc_widget.cpp 文件,然后一切正常了: g++ main.cpp widget.cpp moc_widget.cpp -DQT_CORE_LIB -DQT_GUI_LIB -Ie:\Qt\4.7.0-beta2\include -o main -Le:\Qt\4.7.0-beta2\lib -lQtCore4 -lQtGui4 对 cl 编译器,同样只要添加一个 moc_widget.cpp 即可。 例子四,rcc和uic有点糟蹋这个名字了,本节中不讲例子(因为 rcc 和 uic 概念比较简单)
rcc xxx.qrc -o qrc_xxx.cpp
uic xxx.ui -o ui_xxx.h 这样一来,我们得到是就全是 .h 和 .cpp 的文件了,剩下的工作,你知道的,交给 C++ 编译器就行了。 其他现在来看这个图:是不是很简单了?
可能你看兴趣的内容 |


