QT元对象反射创建对象

1.什么是反射?

反射是指程序在运行时动态获取对象属性与方法的一种机制,即编译器需要将类型信息(属性类型与偏移地址以及成员函数的地址等信息)编译到程序文件中,当程序运行时将这些信息加载到内存中去,做到运行时只根据对象的地址或引用就可以获取到对象的类型信息,从而利用这些信息达到修改或重建对象的目标。

2.反射的作用?

  • 获取类型的信息,包括属性、方法
  • 动态调用方法
  • 动态构造对象
  • 从程序集中获得类型

3.反射的缺点

性能:反射可以理解成是一种解释操作,这个过程总是要慢于直接调用的。当然,性能问题的程度是可以控制的,如果程序在很少涉及的地方使用,性能将不会是一个问题。适用于性能不敏感的部分。

反射模糊了程序内部实际发生的事情,会比直接代码更加复杂增加了理解代码的难度。

缺点不能掩饰其优点,针对不同的场景使用合理的技术才是最高境界。

代码区:

ReflectCreateObject.h

#pragma once
#include <QtWidgets/QWidget>
#include <QObject>
#include <QDebug>
#include <QPushButton>
#include "ui_ReflectCreateObject.h"
class ReflectCreateObject : public QWidget
{
	Q_OBJECT
public:
	/*反射来创建对象,需要把构造函数用 Q_INVOKABLE 进行标记。*/
	Q_INVOKABLE ReflectCreateObject(QWidget *parent = Q_NULLPTR) : QWidget(parent) { ui.setupUi(this); }

	~ReflectCreateObject() {}

	/*通过 Q_PROPERTY 定义类的属性,可以获取使用反射读写对象数据的能力*/
	Q_PROPERTY(QString name READ getName WRITE setName)

		/*需要使用反射调用的方法要用 Q_INVOKABLE 进行标记。*/
		Q_INVOKABLE void func() { qDebug() << "hello world"; }

	QString getName() const { return name; }
	void setName(const QString& m_name) { name = m_name; }
private:
	Ui::ReflectCreateObjectClass ui;
	int id;
	QString name;

};

//Q_DECLARE_METATYPE(ReflectCreateObject)

ToolRegister.h

#pragma once
#include "ReflectCreateObject.h"
#include <QObject>
#include <QDebug>
#include <QMetaType>
#include <QMetaObject>
class ToolRegister : public QWidget
{
	Q_OBJECT

public:
	explicit ToolRegister(QWidget* parent = nullptr) : QWidget(parent)
	{
		//把自定义类型注册到元对象系统中
		qRegisterMetaType<ReflectCreateObject*>("ReflectCreateObject&");

		auto getObjByName = [&](const QString & className)
		{
			/*QMetaType支持的内置类型(QT内置类型都已经注册enum QMetaType::Type,enum QMetaType::Type从0开始
			其中 0 为UnknowType, 1024为用户自定义类型起始位置。):*/
			int type = QMetaType::type(className.toStdString().c_str());

			/*通过用户自定义类型枚举值获取元对象*/
			const QMetaObject* metaObj = QMetaType::metaObjectForType(type);

			/*通过自定义类型构造该类的一个新实例。*/
			if (!instance)
			{
				instance = metaObj->newInstance();
				return instance;
			}
			else
			{
				return instance;
			}
		};

		/*ReflectCreateObject* widget = qobject_cast<ReflectCreateObject*>(getObjByName("ReflectCreateObject*"));
		QScopedPointer<ReflectCreateObject> sp(widget);*/

		/*通过;类名获取实例对象*/
		QObject* demo = getObjByName("ReflectCreateObject");
		/*demo->metaObject()返回与该类绑定的meta-object对象
		QMetaObject::className()可以在运行时以字符串的形式返回类的名字
		不需要C++编译器原生的运行时类型信息(RTTI)的支持。*/
		qDebug() << demo->metaObject()->className();

		/*通过名字动态设置和获取对象属性*/
		auto  readWrite = getObjByName("ReflectCreateObject");
		readWrite->setProperty("name", "123");
		qDebug() << readWrite->property("name").toString();

		/*使用反射调用方法*/
		auto  reflectCallMethod = getObjByName("ReflectCreateObject");
		QMetaObject::invokeMethod(reflectCallMethod, "func");

	}

	~ToolRegister() {}

private:
	QObject* instance = NULL;
};

main.cpp

#include"ToolRegister.h"
#include <QtWidgets/QApplication>
#include <QScopedPointer>
#include <QPushButton>

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	ToolRegister t;
	t.show();
	return a.exec();
}

输出:

ReflectCreateObject
"123"
hello world

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值