Qt 中的物件模型(Object Model)
本節內容主要講了 Qt 物件模型比標準 C++ 物件模型多了什麼內容,並介紹了組成 Qt 物件模型基礎的相關的類。最後說明了為啥 QObject 作為引數時,幾乎都用指標形式的原因。更多內容可參考官方文件 Object Model。
我們使用的標準 C++,其設計的物件模型雖然已經提供了非常高效的 RTTI 支援,但是在某些方面還是不夠靈活。比如在 GUI 程式設計方面,既需要高效的執行效率也需要強大的靈活性,諸如刪除某視窗時可不想把子視窗用程式碼一個個去析構。Qt 將這兩者的優點完美的結合在了一起,創造出了特有的物件模型(Qt Object Model)。
利用這個物件模型,Qt 語言可比 C++ 提供了更多的功能,使用起來相當的方便。那麼只有 Qt 有而 C++ 沒有的特性有:
方便兩個物件間互動的“訊號-槽”機制
非常靈活好用的“物件屬性系統”
可以使用強大的“事件及事件過濾”
可以國際化翻譯字串
可以在 GUI 程式設計中用 Qt 提供的“計時器”完成許多工
以一種自然的方式組織物件父子關係的“物件樹”
當引用物件被銷燬時會自動設為0的指標(主要是 QPointer),而 C++ 指標銷燬時將成為懸空指標
Qt 物件之間的動態轉換支援
可以自定義建立一個 Qt 型別,從而享受 Qt 的其他特性
在繼承 QObject 類的基礎上,一些 Qt 特性是用 C++ 實現的,一些 Qt 特性(如訊號槽、物件屬性)是依靠 Qt 的元物件系統以及 moc工具 實現。
其實,相比 C++ 來說,最大的優點就是元物件系統,真是太強大了。
和物件模型相關的類
以下類構成了 Qt 物件模型的基礎。
QObject 的特殊性
上文提到的新增特性,我們需要將 Qt 物件視為 ID,而不是數值。數值被複制後還是原來的值,ID 被複制了需要指定新的唯一標識。舉個生活中的例子就是,雙胞胎的數值一樣,但是 ID 不同。
禁用複製建構函式、禁用賦值運算子
分配新的 ID 可比賦值要複雜的多,我們可以看下這對於 Qt 來說意味著什麼:
Qt 物件有唯一的 QObject::objectName(),複製一個 Qt 物件我們需要起個什麼新名字呢?
Qt 物件在物件樹中有一個位置,被複制後副本放在哪個層次的哪個位置?
Qt 物件被複制後,原有的訊號槽連線如何轉移到副本?
Qt 物件被複制後,執行時的副本是否包含新增加的屬性值?
所以QObject及其子類都禁用了複製建構函式和賦值運算子。
不能用複製建構函式示例,錯誤示範:
QObject
x
;
QObject
y
(
x
);
不能用賦值運算子示例,錯誤示範:
QObject x;
QObject y;
y = x;
程式設計中的影響
這樣做的結果就是,開發者在某些場景下需要使用 QObject 作為“值”時,必須使用指標傳遞,而不能用值傳遞。
我們知道在各種容器中能以value方式存放的型別,必須有預設的建構函式,複製建構函式和賦值操作。由於 QObject 及子類不能複製和賦值,當我們使用 QList