介绍
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 类,其包含了许多用于类型信息的获取、操作和转换的成员和静态函数。
常用方法
枚举类型
类型 | 枚举 | 解释 |
---|---|---|
Type | Void、Bool、Int、UInt 和 UnknownType 等 | 表示空类型、布尔类型、整型、无符号整型和未知类型。 |
TypeFlag | NeedsConstruction、NeedsDestruction、MovableType、IsEnumeration 和 PointerToQObject 等 | 用于表示类型的构造、析构方法需要的标识、可移动性、枚举和 QObject 指针等特征。 |
flags 类型 TypeFlags 是 TypeFlag 的位域版本,用于标识多个特性。
公共函数
-
QMetaType(int typeId) 构造函数。
-
~QMetaType() 析构函数。
-
void* construct(void* where, const void* copy = Q_NULLPTR) const 在给定的内存位置 where 建立一个新对象,可选择提供已有对象作为参数 copy。返回指向新对象的指针。
-
void* create(const void* copy = Q_NULLPTR) const 创建一个新对象,可选择提供已有对象作为参数 copy。返回指向新对象的指针。
-
void destroy(void* data) const 销毁给定对象指针 data 指向的对象。
-
void destruct(void* data) const 对给定内存位置的对象进行析构。
-
TypeFlags flags() const 返回类型的特性标识。
-
bool isRegistered() const 检查该类型是否已注册。
-
bool isValid() const 检查该类型是否有效。
-
const QMetaObject* metaObject() const 返回类型的元对象。
-
int sizeOf() const 返回该类型所需的内存大小。
静态公共成员
-
bool compare(const void* lhs, const void* rhs, int typeId, int* result) 比较给定的两个对象 lhs 和 rhs 是否相等,并将结果存储在 result 中。
-
void* construct(int type, void* where, const void* copy) 构造给定类型的对象,并将结果存储在 where 中。
-
bool convert(const void* from, int fromTypeId, void* to, int toTypeId) 将 from 类型的对象转换成 toTypeId 类型的对象,并将结果存储在 to 中。
-
void* create(int type, const void* copy = Q_NULLPTR) 创建指定类型的新对象,并可使用给定的 copy 作为初始化值。
-
bool debugStream(QDebug& dbg, const void* rhs, int typeId) 输出给定类型对象 rhs 的调试信息。
-
void destroy(int type, void* data) 销毁指定类型的给定对象 data。
-
void destruct(int type, void* where) 析构指定类型的对象。
-
bool equals(const void* lhs, const void* rhs, int typeId, int* result) 比较给定类型的两个对象 lhs 和 rhs 是否相等,并将结果存储在 result 中。
-
bool hasRegisteredComparators() 检查是否已注册比较器。
-
bool hasRegisteredComparators(int typeId) 检查是否为给定类型已注册比较器。
-
bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId) 检查是否已注册转换函数。
-
bool hasRegisteredConverterFunction() 检查是否已注册任何转换函数。
-
bool hasRegisteredDebugStreamOperator() 检查是否已注册调试输出函数。
-
bool hasRegisteredDebugStreamOperator(int typeId) 检查是否为给定类型已注册调试输出函数。
-
bool isRegistered(int type) 检查是否已注册给定类型。
-
bool load(QDataStream& stream, int type, void* data) 从数据流 stream 中加载给定类型的对象 data。
-
const QMetaObject* metaObjectForType(int type) 返回与给定类型关联的元对象。
-
bool registerComparators() 注册比较器。
-
bool registerConverter() 注册转换函数。
-
bool registerConverter(MemberFunction function) 注册成员函数类型的转换函数。
-
bool registerConverter(MemberFunctionOk function) 注册成员函数类型的转换函数,但不进行类型检查。
-
bool registerConverter(UnaryFunction function) 注册一元函数类型的转换函数。
-
bool registerDebugStreamOperator() 注册调试输出函数。
-
bool registerEqualsComparator() 注册比较器。
-
bool save(QDataStream& stream, int type, const void* data) 将给定类型的对象 data 写入到数据流 stream 中。
-
int sizeOf(int type) 返回给定类型所需的内存大小。
-
int type(const char* typeName) 返回给定类型名称的类型 ID。
-
int type(const QByteArray& typeName) 返回给定类型名称的类型 ID。
-
TypeFlags typeFlags(int type) 返回给定类型的特性标识。
-
const char* typeName(int typeId) 返回给定类型 ID 的类型名称。
非成员函数
-
int qMetaTypeId() 返回 QObject 类型的类型 ID。
-
int qRegisterMetaType(const char* typeName) 注册给定类型名称的元类型,并返回其类型 ID。
-
int qRegisterMetaType() 注册调用者的类型为元类型,并返回其类型 ID。
-
void qRegisterMetaTypeStreamOperators(const char* typeName) 为给定类型名称注册流处理函数。
宏定义
-
Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container) 声明关联式容器的元类型。
-
Q_DECLARE_METATYPE(Type) 声明元类型。
-
Q_DECLARE_OPAQUE_POINTER(PointerType) 声明不透明指针的元类型。
-
Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container) 声明顺序容器的元类型。
-
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_METATYPE
和qRegisterMetaType
用法
Q_DECLARE_METATYPE
和 qRegisterMetaType
都是用来注册自定义类型的函数,但用途略有不同。
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 的各种机制进行集成。