這種寫法用意何在?

由於最近在想辦法將 Qt 集成到 MFC 工程中,偶然調試間, 看到 qtwinmigrate 庫的一段源代碼:

qt-solutions/qmfcapp.cpp at master · qtproject/qt-solutions · GitHub

bool QMfcApp::pluginInstance(Qt::HANDLE plugin)
{
if (qApp)
return FALSE;

QT_WA({
hhook = SetWindowsHookExW(WH_GETMESSAGE, QtFilterProc, 0, GetCurrentThreadId());
}, {
hhook = SetWindowsHookExA(WH_GETMESSAGE, QtFilterProc, 0, GetCurrentThreadId());
});

int argc = 0;
(void)new QApplication(argc, 0);

if (plugin) {
char filename[256];
if (GetModuleFileNameA((HINSTANCE)plugin, filename, 255))
LoadLibraryA(filename);
}

return TRUE;
}

我從來沒見過

(void)new QApplication(argc, 0);

這樣的寫法,很迷惑這句話在幹啥。

有能指點一二的嗎?


可以跟蹤Qt的源碼。

QApplication 繼承 QGuiApplication,而 QGuiApplication 繼承 QCoreApplication。

因此當調用new QApplication(argc, 0); 時,也就調用了 QCoreApplication 的構造函數。QCoreApplication的構造函數調用了QCoreApplication::init(),init函數中有句代碼為

QCoreApplication::self = this;

其中 self 定義為,

static QCoreApplication *self;

所以當調用 (void)new QApplication(argc, 0); 時,看起來沒有啥作用,其實是間接將QCoreApplication::self賦了初始值。再看qApp宏定義為

#define qApp (static_cast&(QCoreApplication::instance()))

QCoreApplication::instance()實現為

static QCoreApplication *instance() { return self; }

在Qt中,qApp表示當前的應用程序。

那段QMfcApp::pluginInstance的代碼,意思是先判斷Qt應用程序類有沒有被初始化,假如還沒有被初始化,就使用

(void)new QApplication(argc, 0);

語句構造出一個實例來初始化。這裡必須使用new讓QApplication分配在堆中,不然在棧中退出作用域時,QCoreApplication::self就失效了。而平常的Qt程序會在main函數入口中寫成。

QApplication app(argc, argv);

這裡不使用new,是因為main函數已經是最頂層,當退出main函數的作用域,程序也就退出了,其實也間接初始化了QCoreApplication::self。

語句前面加(void),大概是防止編譯器報警告。比如函數

void fun(int a, int b)
{
(void)b;
printf("%d
", a);
}

函數的參數為a, b。但b在函數沒有被使用過,這時編譯器有可能發出警告。使用(void)b,可以消除這個警告。有時我們會將這種寫法定義一個宏。比如

# define Q_UNUSED(x) (void)x;

之後就更清楚地表達意圖。

Q_UNUSED(b);


Qt程序的消息泵和某些資源依賴於全局唯一的Application實例。如果不創建出Application實例的話,消息機制沒法運作,某些類型也沒法創建,比如所有的控制項類型。這句話就是創建這個全局唯一實例,在Application的構造函數中會把自己賦值給qApp這個宏指向的全局存儲空間(可視為全局指針變數),使用這個宏就可以拿到這個實例。所以看上去是創建了一個匿名對象,實際上它已經把自己存到一個全局空間里去了,可以認為不匿名了。這樣做,會有風險,比如程序退出時,這個對象的釋放,要考慮清楚,還有,寫某些初始化代碼的時候要注意,不要在qApp被賦值前引用它,能使用的時候,也要注意Application是否構造完全。當然如果你按照Qt本身的思路去使用的話,這些風險相對較小。


qt-solutions/qmfcapp.cpp at master · qtproject/qt-solutions · GitHub

/*! class QMfcApp qmfcapp.h

rief The QMfcApp class provides merging of the MFC and Qt event loops.

QMfcApp is responsible for driving both the Qt and MFC event loop.

It replaces the standard MFC event loop provided by

CWinApp::Run(), and is used instead of the QApplication parent

class.

To replace the MFC event loop reimplement the CWinApp::Run()

function in the CWinApp subclass usually created by the MFC

Application Wizard, and use either the static run() function, or

an instance of QMfcApp created earlier through the static

instance() function or the constructor.

The QMfcApp class also provides a static API pluginInstance() that

drives the Qt event loop when loaded into an MFC or Win32 application.

This is useful for developing Qt based DLLs or plugins, or if the

MFC application"s event handling can not be modified.

*/


推薦閱讀:

string和char數組的區別是什麼以及map可否設置key為char數組?
为什么ASCII被摆放成现在这个样子?——我指的是各个ASCII字符的编号顺序
如何評價 ScyllaDB?
c++primer和more effective c++的一處矛盾?
如何判斷CTP的行情線程是否阻塞?

TAG:QtC開發框架 | C | MFC | VisualC |