簡體   English   中英

QObject 派生的 class 的所有要求是什么?

[英]What are all the requirements of a QObject derived class?

我正在使用 Qt 框架處理我的第一個重要項目,並幫助保持文檔之間的一致性並確保我不會忘記一些小要求,我決定制作一個模板文檔來展示成員函數、宏等. 需要繼承 QObject。 我還希望能夠充分利用 Meta Object 系統。 我是否遺漏了什么或誤解了什么? 如有必要,也可以隨意給予任何一般的 C++ 批評。

我特別關心是否包含復制構造函數的問題。 僅對於不是從 QObject 派生的類才需要嗎?

要求(鏈接到我從中獲得要求的文檔)

  1. 公共默認構造函數(鏈接)
  2. 公共副本構造函數(參見 1) (但與此沖突)
  3. 公共析構函數(見 1)
  4. 使用 Q_OBJECT 宏(鏈接)
  5. 確保可以使用 Q_PROPERTY(...) 宏訪問屬性(鏈接)
  6. 在 Header (link) (link)中用 Q_DECLARE_METATYPE(T) 聲明類型
  7. 在 Header 中聲明與 Q_ENUM(E) 一起使用的任何枚舉(鏈接)

模板 Header

 // Include guards #ifndef CLASSNAME_H #define CLASSNAME_H // Include statements #include <QObject> #include <Th> // Enum definition enum E{ E0, E1, E2 }; // Q_ENUM Macro Q_ENUM(E) // Class declaration class ClassName: public QObject { // Q_OBJECT Macro Q_OBJECT // Q_PROPERTY Macros Q_PROPERTY(T* memberA READ memberA WRITE setMemberA NOTIFY memberAChanged) Q_PROPERTY(int memberB READ memberB WRITE setMemberB NOTIFY memberBChanged) Q_PROPERTY(E memberC READ memberC WRITE setMemberC RESET resetMemberC) public: // Constructors and Destructor ClassName(QObject *parent = nullptr); ClassName() = default; ClassName(const ClassName&) = default; ~ClassName(); // Getters T* memberA() const {return m_memberA;} int memberB() const {return m_memberB;} E memberC() const {return m_memberC;} // Setters void setMemberA(T* newA); void setMemberB(int newB); void setMemberC(E newC); signals: void memberAChanged(T*); void memberBChanged(int); public slots: void resetMemberC(); private slots: private: // Data Members T* m_memberA; int m_memberB; E m_memberC; }; // Meta Object Type Declaration Q_DECLARE_METATYPE(TypeName); // End include guard #endif // CLASSNAME_H

伴隨這個 header 的源文件可能是微不足道的,所以我不會在這里包含它。 盡管如果有人認為演示某些要求或功能會有所幫助,我很樂意將其寫出來。

正如 Jeremy Friesner 所建議的那樣,要求並不那么嚴格。 情況更像是這樣的:

  • 如果您的 class 使用信號和/或槽,它必須同時具有 Q_OBJECT 宏並從 QObject 派生,
  • 如果它只使用其他元對象功能,例如 Q_PROPERTY 聲明,它可以使用 Q_GADGET 宏並且不需要從 QObject 派生,
  • 如果它不需要任何這些,但仍應與 QVariant 等 Qt 模板兼容,則應使用 Q_DECLARE_METATYPE 聲明。 這同樣適用於枚舉和 Q_ENUM。

只有當您需要 class 與 QML 代碼互操作時,才真正需要 Q_PROPERTY/Q_INVOKABLE 接口。

至於您的另一個問題,是的,這是 QObjects 和非 QObjects 之間的重要區別。 元類型必須是可復制的,這就是您手動聲明為元類型的類型需要這樣做的原因,也是系統改為使用 QObject 類型指針的原因,這些指針本身不可復制。 一個最小的 QObject 聲明可以這樣開始:

 #ifndef CLASSNAME_H #define CLASSNAME_H #include <QObject> // Enums in the global namespace cannot be registered; they must be enclosed // in a class and registered with Q_ENUM, or in a namespace declared as // Q_NAMESPACE and registered with Q_ENUM_NS class ClassName: public QObject { Q_OBJECT public: // Default constructor, with explicit specifier to prevent accidental // implicit conversion from a QObject* explicit ClassName(QObject *parent = nullptr); }; // ClassName* is automatically declared as a metatype #endif // CLASSNAME_H

一般來說,我推薦“ 零規則”:如果可能,不要聲明析構函數,也不要聲明任何復制和移動操作,並將它們留給編譯器。 當然,如果您有時間,我也推薦那里的所有其他指南

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM