【Qt之QMetaType】使用

介绍

QMetaType类管理元对象系统中的命名类型。
该类用作QVariant和排队的信号与槽连接中类型的编组辅助器。它将类型名称与类型关联起来,以便可以在运行时动态创建和销毁它。使用Q_DECLARE_METATYPE()声明新类型,以使它们可供QVariant和其他基于模板的函数使用。调用qRegisterMetaType()使类型可供非基于模板的函数使用,例如排队的信号和槽连接。
可以注册具有公共默认构造函数、公共复制构造函数和公共析构函数的任何类或结构。
以下代码分配并销毁MyClass的实例:

  int id = QMetaType::type("MyClass");
  if (id != QMetaType::UnknownType) {
      void *myClassPtr = QMetaType::create(id);
      ...
      QMetaType::destroy(id, myClassPtr);
      myClassPtr = 0;
  }else{
  }

以上代码输出是:
MyClass类型未注册,则输出else语句里的内容,如果注册此类型,则输出if语句里的内容。

如果我们希望流运算符operator<<()operator>>()可以在存储自定义类型的QVariant对象上工作,则自定义类型必须提供operator<<()operator>>()运算符。

type()方法

该函数的功能是返回一个句柄(handle),该句柄指向名为 typeName 的类型(type),如果没有这样的类型,则返回 QMetaType::UnknownType

该函数可以用于在运行时(runtime)根据类型名称查找类型的元信息(meta information),并返回一个句柄以便在程序中使用该类型。如果找不到该类型,则返回一个无效句柄。

该函数属于 Qt 框架中的 QMetaType 类,用于支持动态类型(dynamic typing)。
该代码定义了 Qt 框架中的 QMetaType 类,其包含了许多用于类型信息的获取、操作和转换的成员和静态函数。

常用方法

枚举类型
类型枚举解释
TypeVoid、Bool、Int、UInt 和 UnknownType 等表示空类型、布尔类型、整型、无符号整型和未知类型。
TypeFlagNeedsConstruction、NeedsDestruction、MovableType、IsEnumeration 和 PointerToQObject 等用于表示类型的构造、析构方法需要的标识、可移动性、枚举和 QObject 指针等特征。

flags 类型 TypeFlags 是 TypeFlag 的位域版本,用于标识多个特性。

公共函数
  1. QMetaType(int typeId) 构造函数。

  2. ~QMetaType() 析构函数。

  3. void* construct(void* where, const void* copy = Q_NULLPTR) const 在给定的内存位置 where 建立一个新对象,可选择提供已有对象作为参数 copy。返回指向新对象的指针。

  4. void* create(const void* copy = Q_NULLPTR) const 创建一个新对象,可选择提供已有对象作为参数 copy。返回指向新对象的指针。

  5. void destroy(void* data) const 销毁给定对象指针 data 指向的对象。

  6. void destruct(void* data) const 对给定内存位置的对象进行析构。

  7. TypeFlags flags() const 返回类型的特性标识。

  8. bool isRegistered() const 检查该类型是否已注册。

  9. bool isValid() const 检查该类型是否有效。

  10. const QMetaObject* metaObject() const 返回类型的元对象。

  11. int sizeOf() const 返回该类型所需的内存大小。

静态公共成员
  1. bool compare(const void* lhs, const void* rhs, int typeId, int* result) 比较给定的两个对象 lhs 和 rhs 是否相等,并将结果存储在 result 中。

  2. void* construct(int type, void* where, const void* copy) 构造给定类型的对象,并将结果存储在 where 中。

  3. bool convert(const void* from, int fromTypeId, void* to, int toTypeId) 将 from 类型的对象转换成 toTypeId 类型的对象,并将结果存储在 to 中。

  4. void* create(int type, const void* copy = Q_NULLPTR) 创建指定类型的新对象,并可使用给定的 copy 作为初始化值。

  5. bool debugStream(QDebug& dbg, const void* rhs, int typeId) 输出给定类型对象 rhs 的调试信息。

  6. void destroy(int type, void* data) 销毁指定类型的给定对象 data。

  7. void destruct(int type, void* where) 析构指定类型的对象。

  8. bool equals(const void* lhs, const void* rhs, int typeId, int* result) 比较给定类型的两个对象 lhs 和 rhs 是否相等,并将结果存储在 result 中。

  9. bool hasRegisteredComparators() 检查是否已注册比较器。

  10. bool hasRegisteredComparators(int typeId) 检查是否为给定类型已注册比较器。

  11. bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId) 检查是否已注册转换函数。

  12. bool hasRegisteredConverterFunction() 检查是否已注册任何转换函数。

  13. bool hasRegisteredDebugStreamOperator() 检查是否已注册调试输出函数。

  14. bool hasRegisteredDebugStreamOperator(int typeId) 检查是否为给定类型已注册调试输出函数。

  15. bool isRegistered(int type) 检查是否已注册给定类型。

  16. bool load(QDataStream& stream, int type, void* data) 从数据流 stream 中加载给定类型的对象 data。

  17. const QMetaObject* metaObjectForType(int type) 返回与给定类型关联的元对象。

  18. bool registerComparators() 注册比较器。

  19. bool registerConverter() 注册转换函数。

  20. bool registerConverter(MemberFunction function) 注册成员函数类型的转换函数。

  21. bool registerConverter(MemberFunctionOk function) 注册成员函数类型的转换函数,但不进行类型检查。

  22. bool registerConverter(UnaryFunction function) 注册一元函数类型的转换函数。

  23. bool registerDebugStreamOperator() 注册调试输出函数。

  24. bool registerEqualsComparator() 注册比较器。

  25. bool save(QDataStream& stream, int type, const void* data) 将给定类型的对象 data 写入到数据流 stream 中。

  26. int sizeOf(int type) 返回给定类型所需的内存大小。

  27. int type(const char* typeName) 返回给定类型名称的类型 ID。

  28. int type(const QByteArray& typeName) 返回给定类型名称的类型 ID。

  29. TypeFlags typeFlags(int type) 返回给定类型的特性标识。

  30. const char* typeName(int typeId) 返回给定类型 ID 的类型名称。

非成员函数
  1. int qMetaTypeId() 返回 QObject 类型的类型 ID。

  2. int qRegisterMetaType(const char* typeName) 注册给定类型名称的元类型,并返回其类型 ID。

  3. int qRegisterMetaType() 注册调用者的类型为元类型,并返回其类型 ID。

  4. void qRegisterMetaTypeStreamOperators(const char* typeName) 为给定类型名称注册流处理函数。

宏定义
  1. Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container) 声明关联式容器的元类型。

  2. Q_DECLARE_METATYPE(Type) 声明元类型。

  3. Q_DECLARE_OPAQUE_POINTER(PointerType) 声明不透明指针的元类型。

  4. Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container) 声明顺序容器的元类型。

  5. Q_DECLARE_SMART_POINTER_METATYPE(SmartPointer) 声明智能指针的元类型。

示例

#include <QMetaType>
#include <QDebug>

// 自定义类型
class MyType {
public:
	MyType(){}
    MyType(int value) : m_value(value) {}
    int value() const { return m_value; }
private:
    int m_value;
};

// 注册自定义类型
Q_DECLARE_METATYPE(MyType)

int main()
{
    qRegisterMetaType<MyType>("MyType");
    // 获取自定义类型ID
    int typeID = QMetaType::type("MyType");
    if (typeID == QMetaType::UnknownType) {
        qDebug() << "MyType is not a registered type";
        return -1;
    }

    // 创建自定义类型对象
    void* obj = QMetaType::create(typeID, new MyType(42));
    MyType* myObj = static_cast<MyType*>(obj);
    qDebug() << "Value of myObj: " << myObj->value();

    // 析构自定义类型对象
    QMetaType::destroy(typeID, obj);
    delete myObj;

    return 0;
}

结果:
在这里插入图片描述
该示例中,

  • 使用 Q_DECLARE_METATYPE 宏在全局命名空间中声明了 MyType 类型是元类型。
  • 通过 QMetaType::type 函数获取 MyType 的类型 ID,如果返回值为 QMetaType::UnknownType,则说明该类型没有被注册过。

在 main 函数中,

  • 使用 QMetaType::create 函数创建一个 MyType 对象,并使用static_cast转换为 MyType 指针。
  • 输出该对象的值
  • 再使用 QMetaType::destroy 函数析构对象。

Q_DECLARE_METATYPEqRegisterMetaType用法

Q_DECLARE_METATYPEqRegisterMetaType 都是用来注册自定义类型的函数,但用途略有不同。

Q_DECLARE_METATYPE 宏用于在程序中声明自定义类型是一个元类型。这个宏只是为了告诉 Qt 该类型是元类型,并不会实际注册该类型。当使用该类型时,必须保证已经调用了 qRegisterMetaType 函数将该类型注册为元类型。例如:

// 声明自定义类型是元类型
class MyType {};
Q_DECLARE_METATYPE(MyType);

int main() {
    // 注册自定义类型为元类型
    qRegisterMetaType<MyType>("MyType");
    // ...
}

qRegisterMetaType 函数用于将自定义类型注册为元类型。它必须在程序中的一个全局作用域中调用。例如,通常将它放在 main 函数中。该函数返回已注册类型的元类型 ID,并且该 ID 可以用于在运行时创建该类型的对象。例如:

class MyType {};
Q_DECLARE_METATYPE(MyType);

int main() {
    // 注册自定义类型为元类型
    qRegisterMetaType<MyType>("MyType");

    // 获取 MyType 的元类型 ID
    int typeID = QMetaType::type("MyType");

    // 创建 MyType 对象
    MyType* obj = static_cast<MyType*>(QMetaType::create(typeID));

    // ...
}

总的来说,当你需要在运行时创建某一类型的对象,或者将某一类型用作 Qt 信号/槽中的参数或返回值时,就需要使用 qRegisterMetaType 函数来将该类型注册为元类型。而在该类型的定义头文件中,使用 Q_DECLARE_METATYPE 宏只是为了在程序中声明该类型是元类型。

使用场景

QMetaType 主要用于将 Qt 的信号与槽机制与自定义类型集成。在 Qt 中,信号与槽可以连接任何可转换为 QObject 指针的对象,但是对于信号与槽之间传输自定义类型的数据,则需要将其注册为元类型。

具体来说,当程序使用自定义类型作为信号与槽的参数或返回值时,需要使用 qRegisterMetaType 函数将该类型注册为元类型,否则程序将无法正常编译与运行。例如:

// 自定义类型
struct MyStruct {
    int value;
};

// 注册自定义类型为元类型
Q_DECLARE_METATYPE(MyStruct);
qRegisterMetaType<MyStruct>("MyStruct");

class MyObject : public QObject
{
    Q_OBJECT
public slots:
    // 槽函数,参数为 MyStruct 类型的对象
    void onCustomTypeReceived(MyStruct obj) {
        qDebug() << obj.value;
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    MyObject obj;

    // 连接信号与槽,信号参数为 MyStruct 类型的对象
    QObject::connect(&sender, &Sender::customTypeSent, &obj, &MyObject::onCustomTypeReceived);

    // ...
}

除了信号与槽之外,QMetaType 还可以用于将自定义类型存储到 QVariant 对象中,以及在 QDataStream 中传输自定义类型等场景。总的来说,QMetaType 的主要作用是通过将自定义类型注册为元类型,使其能够与 Qt 的各种机制进行集成。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FreeLikeTheWind.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值