繁体   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