Qt跨平台开发编程技巧总结
一、數據類型
盡量使用Qt提供的數據類型,比如qint32,quint64等。
typedef signed char qint8; /* 8 bit signed */ typedef unsigned char quint8; /* 8 bit unsigned */ typedef short qint16; /* 16 bit signed */ typedef unsigned short quint16; /* 16 bit unsigned */ typedef int qint32; /* 32 bit signed */ typedef unsigned int quint32; /* 32 bit unsigned */ #if defined(Q_OS_WIN) && !defined(Q_CC_GNU) # define Q_INT64_C(c) c ## i64 /* signed 64 bit constant */ # define Q_UINT64_C(c) c ## ui64 /* unsigned 64 bit constant */ typedef __int64 qint64; /* 64 bit signed */ typedef unsigned __int64 quint64; /* 64 bit unsigned */在不同的平臺上,基本的C++類型如short,char,int,long,long long會有不同的字長。
最好使用Qt提供的類型qint8,quint8,qint16,quint16,qint32,quint32,qint64,quint64,這些類型能確保字長是不隨平臺改變的。
二、跨平臺適配
當我們在開發一個功能時,由于在win/linux下各自實現方式不同,故我們需要針對平臺分別實現。
比如,我們需要編寫一個模塊獲取當前系統的名稱。一般來講,有如下幾種方式:
1、多平臺代碼放在一個類中
將win和linux各自的實現代碼放在同一個類中,通過使用如下條件編譯,來隔離不同平臺的代碼。
void Test1::doSomething() { #ifdef WIN32// ...QString str = "on Windows 10, doSomething!"; #else// ...QString str = "on Ubuntu 16.04, doSomething!"; #endifqDebug() << str; }此種方式只適合用于邏輯簡單、代碼較少的代碼段,不適合用于大段代碼跨平臺,或者一個類中分布多個跨平臺函數調用的情況,這樣在整個類中,多個平臺的代碼纏繞在一起,會很混亂,難以維護。
大段代碼,以及跨平臺邏輯復雜,還是建議寫在不同的文件中,以文件為界,來對不同平臺代碼進行隔離。
2、使用接口進行統一
先定義需要獲取的功能接口,然后分別派生出win、linux下的子類,并在子類中完成各自平臺的邏輯代碼。如下:
定義ISysInfo接口(ISysInfo.h)
class ISysInfo { public:virtual QString getSystemName() = 0; };定義Linux下獲取系統名稱實現類(SysInfoLinux.h)
#ifndef SYSINFOLINUX_H #define SYSINFOLINUX_H#ifdef __linux#include "ISysInfo.h"class SysInfoLinux : public ISysInfo { public:virtual QString getSystemName() override{return "Ubuntu 16.04";} };#endif#endif // SYSINFOLINUX_H定義Win下獲取系統名稱實現類(SysInfoWin.h)
#ifndef SYSINFOWIN_H #define SYSINFOWIN_H#ifdef WIN32#include "ISysInfo.h"class SysInfoWin : public ISysInfo { public:virtual QString getSystemName() override{return "Windows 10";} };#endif#endif // SYSINFOWIN_H定義Test2類,Test2.h
#include "ISysInfo.h"class Test2 { public:Test2();~Test2();void doSomething();private:ISysInfo* sysInfo; };Test2.cpp
#include "Test2.h" #include <QDebug> #ifdef WIN32 #include "SysInfoWin.h" #else #include "SysInfoLinux.h" #endifTest2::Test2() { #ifdef WIN32sysInfo = new SysInfoWin(); #elsesysInfo = new SysInfoLinux(); #endif }Test2::~Test2() {delete sysInfo;sysInfo = nullptr; }void Test2::doSomething() {QString str = "on " + sysInfo->getSystemName() + ", doSomething!";qDebug() << str; }在main.cpp進行調用
int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);Test2 test2;test2.doSomething();return a.exec(); }此種方式的好處在于,通過接口可以屏蔽各平臺的實現細節,只要添加好條件編譯#ifdef,則調用時不需要關心到底調用的哪個類。
缺點在于,需要在調用者,代碼中添加條件編譯#ifdef,并需要管理linux和win實現類對象的生命周期。另外,SysInfoWin類需要添加條件編譯#ifdef WIN32,SysInfoLinux類需要添加條件編譯#ifdef __linux,否則編譯出錯,較為麻煩。
3、使用目錄進行隔離
我們分別建立win目錄和linux目錄,分別存放各自平臺實現代碼,并且源文件名稱保持一致SysInfo.h。如下:
然后在pro文件中,添加如下內容,對win/linux進行跨平臺條件編譯。
win32 {HEADERS += Test3/win/SysInfo.hINCLUDEPATH += Test3/win } else {HEADERS += Test3/linux/SysInfo.hINCLUDEPATH += Test3/linux }隨后,實現linux目錄下SysInfo.h內容,如下:
class SysInfo { public:QString getSystemName(){return "Ubuntu 16.04";} };實現win目錄下SysInfo.h內容,如下:
class SysInfo { public:QString getSystemName(){return "Windows 10";} };Test3.cpp中
#include "Test3.h" #include <QDebug> #include "SysInfo.h"void Test3::doSomething() {SysInfo info;QString str = "on " + info.getSystemName() + ", doSomething!";qDebug() << str; }在main.cpp中調用
int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);Test3 test3;test3.doSomething();return a.exec(); }此種方式,通過在工程文件pro中,根據平臺添加參與編譯的源文件,實現跨平臺編譯。
使得調用者,無需關心到底#include "SysInfo.h"文件是哪個平臺,由于pro中設置的關系,當include時會自動找到正確的平臺頭文件。在代碼中不再使用#ifdef條件編譯。
而且,與第2種對比,win和linux目錄下SysInfo類不需要添加各自平臺的條件編譯宏Win32、__linux。所以應該是更方便的。
缺點,是必須手動人工,保證win和linux目錄下SysInfo中,QString getSystemName()函數的一致性,否則在其他平臺編譯時,就可能出現報錯。
三、總結
在實際操作中,我感覺還是推薦使用第3種使用目錄進行隔離的方式,
雖然有缺點,但是只要在需要跨的平臺上編譯通過,基本就沒有大問題,編譯期,接口一致性還是容易解決。
另外在小段代碼需要跨平臺處理時,推薦使用第1種方式。
當然在跨平臺編程中,還有許多的注意點,以后有機會再繼續分享。
若對你有幫助,歡迎點贊、收藏、評論,你的支持就是我的最大動力!!!
同時,阿超為大家準備了豐富的學習資料,歡迎關注公眾號“超哥學編程”,即可領取。
本文涉及工程代碼,公眾號回復:17CrossPlatform,即可下載。
總結
以上是生活随笔為你收集整理的Qt跨平台开发编程技巧总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Modelsim库编译
- 下一篇: pytest合集(4)— 使用pytes