九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
從 C++ 到 Qt

Qt 是 C++ 的庫,Qt在ansi C++ 的基礎(chǔ)上進(jìn)行了一點(diǎn)擴(kuò)展。

但國內(nèi)似乎比較浮躁,學(xué)Qt的很多連基本的C++如何編譯似乎都不太清楚。本文舍棄IDE或qmake、cmake等工具的束縛,嘗試通過幾個(gè)例子,一步一步從標(biāo)準(zhǔn) C++ 的編譯過渡到 Qt 的編譯。

本文涉及的都是最基本的東西,或許可以說,只要你用C++ Qt,不管是通過哪種工具(qmake、cmake、boost.build、qtcreator、vs2008、Eclipse、...),本文的內(nèi)容都是需要理解的(盡管真正寫程序時(shí),我們都不會(huì)直接用C++編譯器來編譯Qt程序)。

如果你對(duì)命令行比較恐懼,或許愿意先看看我原來整理的這個(gè) http://wiki.ubuntu.org.cn/Gcchowto

例子一:簡單的控制臺(tái)程序

一個(gè)很簡單的例子,沒用到Qt擴(kuò)展:(也就是說,這是一個(gè)普通的C++程序)

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
qDebug()<<"hello qt!";
app.exec();
}

我們都知道,編譯一個(gè)C++的程序,無非是 編譯預(yù)處理,編譯、鏈接

  • 編譯預(yù)處理器:頭文件路徑 和 必要的宏
  • 編譯器:一些編譯參數(shù)
  • 鏈接器:一些鏈接參數(shù) 和 要鏈接的庫

g++

簡單一行命令,即可生成 main.exe (linux下,則生成可執(zhí)行程序 main)

g++ main.cpp -DQT_CORE_LIB -Ie:\Qt\4.7.0\include -o main -Le:\Qt\4.7.0\lib -lQtCore4

單行命令,很簡單:

  • -I 指定頭文件路徑
  • -L 指定庫文件路徑
  • -l 指定需要鏈接的庫
  • -D 定義必要的宏(其實(shí)對(duì)這個(gè)小程序,這個(gè)宏也沒必要用)
  • -o 指定生成的可執(zhí)行文件名

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

依然很簡單

  • -I 頭文件路徑
  • -D 定義必要的宏
  • -Fe 指定可執(zhí)行程序文件名
  • -link 后面是鏈接器參數(shù)
    • -LIBPATH 庫文件路徑

例子二:簡單的GUI程序

這次稍微復(fù)雜一點(diǎn),不是單一的控制臺(tái)程序,而是一個(gè)簡單的GUI程序

  • main.cpp

#include <QtGui/QApplication>
#include "widget.h"

int main(int argc, char** argv)
{
QApplication app(argc, argv);
Widget w;
w.show();
return app.exec();
}
  • widget.h

#include <QtGui/QWidget>
class Widget : public QWidget
{
public:
Widget(QWidget * parent=NULL);
};
  • widget.cpp

#include "widget.h"

Widget::Widget(QWidget * parent)
:QWidget(parent)
{
}

同樣,這個(gè)程序未使用Qt的擴(kuò)展,直接用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

因?yàn)槲覀兪褂昧薗tGui模塊,所以和前面相比:

  • 增加了 -DQT_GUI_LIB 和 -lQtGui4
  • 多了一個(gè)文件 widget.cpp

注意: Windows下


如果在非windows平臺(tái)下,這條命令就可以了。但windows下,你知道的:分console和windows兩個(gè)鏈接子系統(tǒng),而且入口函數(shù)分 main 和 WinMain 。

這條命令,編譯出的 main.exe 會(huì)彈出控制臺(tái)。要想不要控制臺(tái),則使用下面的命令:

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 -lqtmain -Wl,-subsystem,windows

多了兩個(gè)選項(xiàng):

  • qtmain 該庫中一個(gè)WinMain 函數(shù),它會(huì)調(diào)用我們的代碼的main函數(shù)。即對(duì)編譯器來說:入口函數(shù)的名字變了

  • -Wl,-subsystem,windows 你知道的,鏈接windows子系統(tǒng)

cl

同windows下的g++基本一樣,帶控制臺(tái):

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

不帶控制臺(tái):

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

分析同上:指定鏈接子系統(tǒng),啟用WinMain入口函數(shù)

多文件的程序如何管理

直接調(diào)用編譯器有什么壞處呢?

  • 參數(shù)多啊,每次手動(dòng)輸入,難免出錯(cuò)。(例子中我們用的參數(shù)已經(jīng)盡可能少了,可能都還是讓你眼暈了)。
  • 其次呢,很重要的一點(diǎn),每次只要一個(gè)文件修改,所有東西都要重新編譯。

改變這種狀況的辦法,傳統(tǒng)的就是寫 Makefile,然后編譯時(shí)只需要輸入 make 就行了,他會(huì)判斷哪些文件被改動(dòng)需要重新編譯。

另外就是VS等一些IDE自己提供的功能。下面簡單看一下本例子對(duì)應(yīng)makefile文件:

mingw32-make的Makefile文件

CPPFLAGS = -DQT_CORE_LIB -DQT_GUI_LIB -Ie:\Qt\4.7.0\include
LDFLAGS = -Le:\Qt\4.7.0\lib -lQtCore4 -lQtGui4 -lqtmain -Wl,-subsystem,windows

objects = main.o widget.o
dest = main

$(dest) : $(objects)
g++ -o $@ $(objects) $(LDFLAGS)

nmake的Makefile文件

CPPFLAGS = -ID:/Qt/4.7.0/include -DQT_CORE_LIB -DQT_GUI_LIB -MD
LDFLAGS = -LIBPATH:D:/Qt/4.7.0/lib -subsystem:windows qtmain.lib QtCore4.lib QtGui4.lib
objects = main.obj widget.obj
dest = main.exe
$(dest) : $(objects)
link $(objects) $(LDFLAGS)

對(duì)此不做介紹,因?yàn)镸akefile編寫也是一門學(xué)問。相當(dāng)難寫,所有才有qmake、cmake這些工具來幫我們生成Makefile文件

例子三:引入moc

Qt 對(duì) C++ 的擴(kuò)展主要是3個(gè)方面:

  • 元對(duì)象系統(tǒng),包含Q_OBJECT宏的文件(.h, .cpp等)需要 moc 預(yù)處理
  • 資源系統(tǒng),.qrc 文件 需要 rcc 進(jìn)行預(yù)處理
  • 界面系統(tǒng),.ui 文件 需要 uic 進(jìn)行預(yù)處理

這3者之中,元對(duì)象系統(tǒng)最復(fù)雜,也是 Qt 程序中重要的。其他兩個(gè)你都可以不要,唯獨(dú)這個(gè)不要就有點(diǎn)不像話了(沒它還叫Qt程序么?像我們前面寫的,只不過是普通的C++程序)

廢話少說,看例子:(修改前面的widget.h,加入Q_OBJECT)

#include <QtGui/QWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget * parent=NULL);
};

如何編譯這個(gè)程序呢?例子二中的命令還能用嗎?不妨試試:

  • 哇,輸出好豐富啊!

來自 g++ 的問候:

main.o:main.cpp:(.text$_ZN6WidgetD1Ev[Widget::~Widget()]+0xb): undefined reference to `vtable for Widget'
main.o:main.cpp:(.text$_ZN6WidgetD1Ev[Widget::~Widget()]+0x15): undefined reference to `vtable for Widget'
widget.o:widget.cpp:(.text+0x39): undefined reference to `vtable for Widget'
widget.o:widget.cpp:(.text+0x43): undefined reference to `vtable for Widget'

來自 cl 的問候:

widget.obj : error LNK2001: 無法解析的外部符號(hào) "public: virtual struct QMetaObject const * __thiscall Widget::metaObject(void)const " (?metaObject@Widget@@UBEPBUQMetaObject@@XZ)
widget.obj : error LNK2001: 無法解析的外部符號(hào) "public: virtual void * __thiscall Widget::qt_metacast(char const *)" (?qt_metacast@Widget@@UAEPAXPBD@Z)
widget.obj : error LNK2001: 無法解析的外部符號(hào) "public: virtual int __thiscall Widget::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@Widget@@UAEHW4Call@QMetaObject@@HPAPAX@Z)

發(fā)生了什么?

添加一個(gè)宏后,發(fā)生了什么?我們看看編譯器將宏展開后是什么樣子的:

#include <QtGui/QWidget>
class Widget : public QWidget
{
static const QMetaObject staticMetaObject;
virtual const QMetaObject *metaObject() const;
virtual void *qt_metacast(const char *);
virtual int qt_metacall(QMetaObject::Call, int, void **);
...
public:
Widget(QWidget * parent=NULL);
};

一下子多出來這么多函數(shù),而且還沒有函數(shù)體,不出錯(cuò)才怪。如何生成函數(shù)體呢?這正是moc所做的:

moc widget.h -o moc_widget.cpp

這樣一來,這些函數(shù)都在 moc_widget.cpp 被實(shí)現(xiàn)了,只要我們將該文件一塊編譯鏈接就行了

對(duì)g++來說,在例子二的基礎(chǔ)上,直接添加一個(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

對(duì) cl 編譯器,同樣只要添加一個(gè) moc_widget.cpp 即可。

例子四,rcc和uic

有點(diǎn)糟蹋這個(gè)名字了,本節(jié)中不講例子(因?yàn)?rcc 和 uic 概念比較簡單)

  • 如果我們用了資源,那么需要一個(gè) xxx.qrc 文件,這個(gè)文件呢,C++ 編譯器不認(rèn)識(shí),于是

rcc xxx.qrc -o qrc_xxx.cpp
  • 如果我們用了designer設(shè)計(jì)的界面 .ui。C++ 編譯器不認(rèn)識(shí)這個(gè)文件,于是

uic xxx.ui -o ui_xxx.cpp

這樣一來,我們得到是就全是 .h 和 .cpp 的文件了,剩下的工作,你知道的,交給 C++ 編譯器就行了。

其他

現(xiàn)在來看這個(gè)圖:是不是很簡單了?

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Qt項(xiàng)目文件詳解
寫qt程序的步驟及第一個(gè)QT程序
QT工程中的文件介紹----*.pro文件
QT的pro文件編寫,高效簡潔,,路徑設(shè)置 有空格 引入系統(tǒng)環(huán)境變量等
Qmake VS Cmake
QT編程中常見注意事項(xiàng)
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服