Qt 如何使用反射?
c++ 反射 标准库暂时还没有,那我们来看看如何使用 qt 来进行反射.
反射类的案例
1. 通过注册的类型需找 id 进行实例化该类
myclass.h
#include <QtCore>
class MyClass
{
public:
MyClass() {}
QString name(){
return "cheungxiongwei";
}
};
//声明元对象类型
Q_DECLARE_METATYPE(MyClass)
main.cpp
#include <QCoreApplication>
#include "myclass.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 注册自定义的类
qRegisterMetaType<MyClass>("MyClass");
// 通过静态函数获取注册类的 id,id 不为 0 时,则获取成功.大部分基础类型都可以获取到 id,如 QString QByteArray
int id = QMetaType::type("MyClass");
if(id != 0){
// 根据 id 创建该类型
void *myClass = QMetaType::create(id);
// 转换指针
MyClass *my = static_cast<MyClass*>(myClass);
// 调用函数
qDebug() << my->name();
// 这里可以添加一些自己自己的处理函数
// 释放内存
QMetaType::destroy(id, myClass);
myClass = nullptr;
}
return a.exec();
}
2. 通过调用静态成员变量 MyClass::staticMetaObject
获取元对象信息,比较类名称来确定 QMetaObject
myclass.h
class MyClass1 : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE MyClass1() {}
virtual ~MyClass1() {}
// 添加宏 Q_INVOKABLE 可以使用 invokeMethod 调用该函数
Q_INVOKABLE QString name(QString name){
return name.append("xiongwei");
}
QString name_(){
return "cheungxiongwei";
}
};
class MyClass2 : public QObject
{
Q_OBJECT
public:
MyClass2() {}
virtual ~MyClass2() {}
};
inline QMetaObject GetMetaObjectByClassName(QString className)
{
QMetaObject metaObject;
if(className.compare("MyClass1") == 0){
metaObject = MyClass1::staticMetaObject;
}else if (className.compare("MyClass2") == 0){
metaObject = MyClass2::staticMetaObject;
}
// and so on, you get the idea ...
return metaObject;
}
inline QMetaObject GetMetaObjectByClassName(QString className)
{
QMetaObject metaObject;
if(className.compare("MyClass1") == 0){
metaObject = LayoutCameraGrab::staticMetaObject;
}else if (className.compare("MyClass2") == 0){
metaObject = LayoutImageRead::staticMetaObject;
}
// and so on, you get the idea ...
return metaObject;
}
inline void printMetaObject(const QMetaObject *metaObject)
{
qDebug() << "Class:" << metaObject->className();
for(int i = 0;i < metaObject->classInfoCount();++i){
qDebug() << "ClassInfo:" << metaObject->classInfo(i).name() << metaObject->classInfo(i).value();
}
for(int i = 0;i < metaObject->constructorCount();++i){
qDebug() << "Constructor:" << metaObject->constructor(i).name() << metaObject->constructor(i).parameterNames();
}
for(int i = 0;i < metaObject->enumeratorCount();++i){
qDebug() << "Enum:" << metaObject->enumerator(i).name();
}
for(int i = 0;i < metaObject->methodCount();++i){
qDebug() << "Method:" << metaObject->method(i).name() << metaObject->method(i).parameterNames() << metaObject->method(i).tag();
}
for(int i = 0;i < metaObject->propertyCount();++i){
qDebug() << "Proper:" << metaObject->property(i).name();
}
}
main.cpp
Note that only constructors that are declared with the Q_INVOKABLE modifier are made available through the meta-object system.
上面一句话说的是只有在构造函数前面添加 Q_INVOKABLE
宏后才可以 QMetaObject
的函数 newInstance
创建该实例.
#include <QCoreApplication>
#include "myclass.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 通过类名称获取元对象类型
QMetaObject metaObject = GetMetaObjectByClassName("MyClass1");
// 实例化该类
QObject *object = metaObject.newInstance();
if(object){
QString ret;
// 调用 name 带参数函数
// 如果未加 Q_INVOKABLE 宏,则输出 QMetaObject::invokeMethod: No such method MyClass1::name<QString>
metaObject.invokeMethod(
object,
"name",
Qt::DirectConnection,
Q_RETURN_ARG(QString,ret),
Q_ARG(QString,"cheung"));
// 打印返回值
qDebug() << ret;
// 转换指针类型调用未加 Q_INVOKABLE 宏的函数.
MyClass1 *myclass = static_cast<MyClass1*>(object);
Debug() << myclass->name_();
}
qDebug() << object;
return a.exec();
}