百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Qt元对象系统:QMetaMethod、QMetaObject

liebian365 2024-11-12 13:10 12 浏览 0 评论

Qt的元对象系统为对象间通信、运行时类型信息和动态属性系统提供了信号和槽机制。

元对象系统基于三个方面:

  • QObject 类为可以利用元对象系统的对象提供基类。
  • Q_OBJECT 宏用于启用元对象特性,例如动态属性、信号和槽。

元对象编译器(moc)为每个 QObject 子类提供实现元对象特性所需的代码。

moc 工具读取C++源文件。如果它在类中找到包含 Q_OBJECT 宏声明,则生成另一个C++源文件,其中包含每个类的元对象代码。生成的源文件要么包含到类的源文件中,要么更通常是编译并与类的实现链接。

除了提供对象间通信的信号和槽机制,元对象代码还提供以下功能:

QObject::metaObject() 返回类的关联元对象。

QMetaObject::className() 在运行时返回类名为字符串,而不需要通过C++编译器支持本机运行时类型信息(RTTI)。

  • QObject::inherits() 返回对象是否是继承 QObject 或其子类。
  • QObject::tr() 为国际化转换字符串。
  • QObject::setProperty() 和 QObject::property() 按名称动态设置和获取属性。
  • QMetaObject::newInstance() 构造类的新实例。

也可以在 QObject 类上使用 qobject_cast() 执行动态强制转换。qobject_cast() 函数的行为类似于标准C++动态 dynamic_cast(),其优点是不需要RTTI支持。它尝试将其参数强制转换为尖括号中指定的指针类型,如果对象的类型正确(在运行时确定),则返回非零指针;如果对象的类型不兼容,则返回 nullptr。

如果使用 QObject 作为基类却不使用 Q_OBJECT 宏和元对象代码,那么信号和槽以及其他特性都将不可用。从元对象系统的观点来看,没有元代码的 QObject 子类等同于有元对象代码的最近祖先。例如,这意味着 QMetaObject::className()将不返回类的实际名称,而是返回该祖先的类名。



因此,强烈建议 QObject 的所有子类使用Q_OBJECT宏,而不管它们是否实际使用信号槽和属性。

QMetaMethod

一、描述

此类提供有关成员函数的元数据。

二、类型成员

1、enum QMetaMethod::Access:此枚举描述了方法的访问级别,遵循C++中使用的约定。

  • Private
  • Protected
  • Public

2、enum QMetaMethod::MethodType:成员函数类型

  • Method:普通成员函数。
  • Signal:信号。
  • Slot:槽。
  • Constructor:构造函数。

三、成员函数

1、QMetaMethod::Access access()

返回此方法的访问级别。

2、【static】template <typename PointerToMemberFunction> QMetaMethod fromSignal(PointerToMemberFunction signal)

返回与给定信号对应的元方法,如果信号不是类的信号,则返回无效的 QMetaMethod。

QMetaMethod destroyedSignal = QMetaMethod::fromSignal(&QObject::destroyed);

3、bool invoke(QObject *object, Qt::ConnectionType connectionType, QGenericReturnArgument returnValue, QGenericArgument val0 = QGenericArgument(nullptr), QGenericArgument val1 = QGenericArgument(), ......)

对 object 对象调用此方法。如果可以调用,则返回 true。如果没有此类成员或参数不匹配,则返回false。

调用可以是同步的,也可以是异步的,具体取决于 connectionType:

  • Qt::DirectConnection:立即调用该成员。
  • Qt::QueuedConnection:一旦应用程序进入主事件循环,就会发布一个 QEvent 并调用该成员。
  • Qt::AutoConnection:如果对象与调用者位于同一线程中,则会同步调用该成员;否则将异步调用该成员。

此方法调用的返回值放在 returnValue 中。如果调用是异步的,则无法计算返回值。

最多可以向这个方法调用传递十个参数(val0、val1、val2、val3、val4、val5、val6、val7、val8和val9)。

QGenericArgument 和 QGenericReturnArgument 是内部帮助程序类。因为可以动态调用信号和槽,所以必须使用 Q_ARG() 和 Q_RETURN_ARG() 宏将参数括起来。

此方法不会测试参数的有效性,object 必须是构造此 QMetaMethod 的 QMetaObject 类的实例。参数的类型必须与方法预期的类型相同,否则行为未定义。

在 QPushButton 上异步调用 animateClick():

int methodIndex = pushButton->metaObject()->indexOfMethod("animateClick()");
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(pushButton, Qt::QueuedConnection);

对于异步方法调用,参数必须是Qt的元对象系统已知的类型。对于自定义类型,在调用之前需要调用 qRegisterMetaType() 注册数据类型。

同步调用某个对象 obj 上的 QString compute(QString,int,double):

QString retVal;
QByteArray normalizedSignature = QMetaObject::normalizedSignature("compute(QString, int, double)");
int methodIndex = obj->metaObject()->indexOfMethod(normalizedSignature);
QMetaMethod method = obj->metaObject()->method(methodIndex);
method.invoke(obj,
Qt::DirectConnection,
Q_RETURN_ARG(QString, retVal),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7));

如果没有按指定顺序精确地接受一个QString、一个int和一个double,则调用将失败。

bool invoke(QObject *object, QGenericReturnArgument returnValue, QGenericArgument val0 = QGenericArgument(0), QGenericArgument val1 = QGenericArgument(), ......)

以 Qt::AutoConnection 调用此方法。

bool invoke(QObject *object, Qt::ConnectionType connectionType, QGenericArgument val0 = QGenericArgument(0), QGenericArgument val1 = QGenericArgument(), ......)

如果不关心成员的返回值,则可以使用此重载。

bool invoke(QObject *object, QGenericArgument val0 = QGenericArgument(0), QGenericArgument val1 = QGenericArgument(), ......)

以 Qt::AutoConnection 调用此方法,并忽略返回值。

4、bool invokeOnGadget(void *gadget, QGenericReturnArgument returnValue, QGenericArgument val0 = QGenericArgument(nullptr), QGenericArgument val1 = QGenericArgument(), ......)

在使用 Q_GADGET 的对象上调用此方法。如果可以调用成员,则返回 true。如果没有此类成员或参数不匹配,则返回 false。

调用始终是同步的。

此方法调用的返回值放在 returnValue 中。最多可以向这个方法调用传递十个参数(val0、val1、val2、val3、val4、val5、val6、val7、val8和val9)。

此方法不会测试参数的有效性,gadget 必须是构造此 QMetaMethod 的 QMetaObject 类的实例。参数的类型必须与方法预期的类型相同,否则行为未定义。

见 QObject。

class test
{
Q_GADGET
public:
test() = default;
Q_INVOKABLE QString showInfo()
{
return "xxxxxxxxxxx";
}
};

int main(int argc, char *argv[])
{
test t;
QByteArray normalizedSignature = test::staticMetaObject.normalizedSignature("showInfo()");
int funIndex = test::staticMetaObject.indexOfMethod(normalizedSignature);
QMetaMethod method = test::staticMetaObject.method(funIndex);
QString retVal;
qDebug()<<method.invokeOnGadget(&t,Q_RETURN_ARG(QString,retVal));//true
qDebug()<<retVal;//"xxxxxxxxxxx"
}
bool invokeOnGadget(void *gadget, QGenericArgument val0 = QGenericArgument(0), QGenericArgument val1 = QGenericArgument(), ......)

为 gadget 调用此方法并忽略返回值。

5、bool isConst()

该方法是否是 const 限定的。

6、bool isValid()

此方法是否有效(可以内省和调用)。

7、int methodIndex()

返回此方法的索引。

8、QByteArray methodSignature()

返回此方法的签名。

class test
{
Q_GADGET
public:
test() = default;
Q_INVOKABLE QString showInfo(int a)
{
return "xxxxxxxxxxx";
}
};

int main(int argc, char *argv[])
{
test t;
QByteArray normalizedSignature = test::staticMetaObject.normalizedSignature("showInfo(int)");
int funIndex = test::staticMetaObject.indexOfMethod(normalizedSignature);
QMetaMethod method = test::staticMetaObject.method(funIndex);
qDebug()<<method.methodSignature();//"showInfo(int)"
}

9、QMetaMethod::MethodType methodType()

返回此方法的类型(信号、槽或方法)。

10、QByteArray name()

返回此方法的名称。(函数名)

11、int parameterCount()

返回此方法的参数个数。

12、QMetaType parameterMetaType(int index)

返回给定索引的参数的元类型。

13、QList<QByteArray> parameterNames()

返回参数名称列表。

class test
{
Q_GADGET
public:
test() = default;
Q_INVOKABLE QString showInfo(int a,QString b)
{
return "xxxxxxxxxxx";
}
};

int main(int argc, char *argv[])
{
test t;
QByteArray normalizedSignature = test::staticMetaObject.normalizedSignature("showInfo(int,QString)");
int funIndex = test::staticMetaObject.indexOfMethod(normalizedSignature);
QMetaMethod method = test::staticMetaObject.method(funIndex);
qDebug()<<method.parameterNames();//QList("a", "b")
}

14、int parameterType(int index)

返回给定索引处的参数类型。返回值是使用 QMetaType 注册的类型,如果该类型未注册,则为 QMetaType::UnknownType。

15、QByteArray parameterTypeName(int index)

返回位置索引处类型的名称。

class test
{
Q_GADGET
public:
test() = default;
Q_INVOKABLE QString showInfo(int a,QString b)
{
return "xxxxxxxxxxx";
}
};

int main(int argc, char *argv[])
{
test t;
QByteArray normalizedSignature = test::staticMetaObject.normalizedSignature("showInfo(int,QString)");
int funIndex = test::staticMetaObject.indexOfMethod(normalizedSignature);
QMetaMethod method = test::staticMetaObject.method(funIndex);
qDebug()<<method.parameterTypeName(1);//"QString"
}

16、QList<QByteArray> parameterTypes()

返回参数类型列表。

17、QMetaType returnMetaType()

返回此方法的返回值类型。

18、int returnType()

返回此方法的返回值类型。返回值是使用 QMetaType 注册的类型,如果该类型未注册,则为QMetaType::UnknownType。

19、int revision()

如果使用 Q_REVISION 设置了方法的修订版本,则返回方法修订版本,否则返回 0。

20、const char * tag()

返回与此方法关联的标签。标签是由 moc 识别的特殊宏,可以添加有关方法的额外信息。

可以使用标签对方法进行不同的注释,并根据应用程序的特定需要对它们进行处理。

可以通过以下方式在函数声明中添加标签信息:

#ifndef Q_MOC_RUN
#define MY_CUSTOM_TAG
#endif

class test
{
Q_GADGET
public:
test() = default;
Q_INVOKABLE MY_CUSTOM_TAG QString showInfo(int a,QString b)
{
return "xxxxxxxxxxx";
}
};

int main(int argc, char *argv[])
{
test t;
QByteArray normalizedSignature = test::staticMetaObject.normalizedSignature("showInfo(int,QString)");
int funIndex = test::staticMetaObject.indexOfMethod(normalizedSignature);
QMetaMethod method = test::staticMetaObject.method(funIndex);
qDebug()<<method.tag();// MY_CUSTOM_TAG
}

必需使用 #ifndef Q_MOC_RUN 包围定义。

21、const char * typeName()

返回此方法的返回值类型名称。

class test
{
Q_GADGET
public:
test() = default;
Q_INVOKABLE QString showInfo(int a,QString b)
{
return "xxxxxxxxxxx";
}
};

int main(int argc, char *argv[])
{
test t;
QByteArray normalizedSignature = test::staticMetaObject.normalizedSignature("showInfo(int,QString)");
int funIndex = test::staticMetaObject.indexOfMethod(normalizedSignature);
QMetaMethod method = test::staticMetaObject.method(funIndex);
qDebug()<<method.typeName();// QString
}

四、宏成员

1、Q_METAMETHOD_INVOKE_MAX_ARGS

等于可用于通过 QMetaMethod::invoke() 执行方法的最大参数个数。


免费学习C++ Qt开发教程视频,点击下面链接免费报名领取视频学习资料

C/C++项目实战/Qt5/C语言/c++/数据库/OpenCV/MFC/QT项目-学习视频教程-腾讯课堂

QMetaObject

一、描述

此类包含有关Qt对象的元信息。Qt为应用程序中使用的每个 QObject 子类创建一个 QMetaObject 实例,该实例存储 QObject 子类的所有元信息。

二、静态成员函数

1、QByteArray normalizedSignature(const char *method)

规范化给定方法的签名。Qt使用规范化签名来决定给定的信号和槽是否兼容。

规范化:

将空格减少到最小

将 const 移到最前面适当的位置,

用值替换 const 引用。

signals:
void userNameChanged(const QString & userName);
void passwordChanged(const QString password);

qDebug()<<this->staticMetaObject.normalizedSignature(SIGNAL(userNameChanged(const QString & userName)));
qDebug()<<this->staticMetaObject.normalizedSignature(SIGNAL(passwordChanged(const QString password)));


2、QByteArray normalizedType(const char *type)

规范化类型。

QByteArray normType = QMetaObject::normalizedType(" int const *");

// normType == "const int*"

3、bool checkConnectArgs(const char *signal, const char *method)

信号和方法参数是否兼容。信号和方法均应规范化。

static const QMetaObject meteObject = this->staticMetaObject;
qDebug()<<meteObject.checkConnectArgs(meteObject.normalizedSignature(SIGNAL(userNameChanged(const QString & userName))),
meteObject.normalizedSignature(SLOT(onUserChanged(const QString & userName))));

qDebug()<<meteObject.checkConnectArgs(SIGNAL(userNameChanged(const QString & userName)),
SLOT(onUserChanged(const QString & userName)));
bool checkConnectArgs(const QMetaMethod &signal, const QMetaMethod &method)
signals:
void userNameChanged(const QString & userName);

private slots:
void onUserChanged(const QString &userName);

auto meteObject = this->staticMetaObject;
auto signalIndex = meteObject.indexOfSignal("userNameChanged(QString)");
QMetaMethod signal = meteObject.method(signalIndex);

auto funIndex = meteObject.indexOfMethod("onUserChanged(QString)");
QMetaMethod fun = meteObject.method(funIndex);
qDebug()<<meteObject.checkConnectArgs(signal,fun);//true

4、void connectSlotsByName(QObject *object)

递归搜索给定对象及其所有子对象,并将来自这些子对象的匹配信号连接到以下形式的槽:

void on_<object name>_<signal name>(<signal parameters>);

假设一个类型为 QPushButton 的对象,对象名为 button1,捕捉按钮 clicked() 信号的槽为:void on_button1_clicked();

5、bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument(nullptr), QGenericArgument val1 = QGenericArgument(), ......)

调用对象obj上的成员 member(信号或槽)。如果可以调用该成员,则返回 true。如果没有此成员或参数不匹配,则返回false。

调用可以是同步的,也可以是异步的,具体取决于 type:

  • Qt::DirectConnection:立即调用该成员。
  • Qt::QueuedConnection:应用程序进入主事件循环后发送 QEvent 并调用该成员。
  • Qt::BlockingQueuedConnection:将以与 Qt::QueuedConnection 相同的方式调用该成员,但当前线程将阻塞。使用此连接类型与在同一线程中的对象之间通信将导致死锁。
  • Qt::AutoConnection:如果 obj 与调用者位于同一线程中,则同步调用该成员,否则将异步调用该成员。

调用的返回值放在 ret 中。如果调用是异步的,则无法计算返回值。

最多可以向成员函数传递十个参数(val0、val1、val2、val3、val4、val5、val6、val7、val8、val9)。

QGenericArgument 和 QGenericReturnArgument 是内部帮助程序类。因为可以动态调用信号和槽,所以必须使用 Q_ARG() 和 Q_RETURN_ARG() 宏将参数括起来。Q_ARG() 接受类型名称和该类型的常量引用,Q_RETURN_ARG() 接受类型名和非常量引用。

只需要将信号或槽的名称传递给此函数,而不需要传递整个签名(只传递名称不用包含参数)。

例如,在 QThread 上异步调用 quit() 槽:

QMetaObject::invokeMethod(thread, "quit",Qt::QueuedConnection);

对于异步方法调用,参数必须是Qt的元对象系统已知的类型,因为Qt需要复制参数以在幕后事件中存储它们。对于自定义类型,在调用之前需要使用 qRegisterMetaType() 注册数据类型。

示例:同步调用某个任意对象 obj 上的 compute(QString, int, double) 槽:

QString retVal;
QMetaObject::invokeMethod(obj, "compute", Qt::DirectConnection,
Q_RETURN_ARG(QString, retVal),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7));

这里如果 “compute” 槽没有按指定顺序精确地接受一个QString、一个int、一个double,则调用将失败。

bool invokeMethod(QObject *obj, const char *member, QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument(0), ......)

此重载始终使用连接类型 Qt::AutoConnection 调用成员。

bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericArgument val0 = QGenericArgument(0), ......)

如果成员函数无返回值,则可以使用此重载。

bool invokeMethod(QObject *obj, const char *member, QGenericArgument val0 = QGenericArgument(0), ......)
此重载使用连接类型 Qt::AutoConnection 调用成员函数,并忽略返回值。
template <typename Functor, typename FunctorReturnType> bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr)

在 context 的事件循环中调用 function 。function 可以是函子或指向成员函数的指针。

如果可以调用函数,则返回 true。如果没有此类函数或参数不匹配,则返回 false。

函数调用的返回值放在 ret 中。

class test
{
public:
test() = default;
void operator()()
{
qDebug()<<"run test()";
}
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.show();
QMetaObject::invokeMethod(&a,test());

return a.exec();
}
template <typename Functor, typename FunctorReturnType> bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret)

使用连接类型 Qt::AutoConnection 在 context 的事件循环中调用 function。function 可以是函子或指向成员函数的指针。

如果可以调用函数,则返回 true。如果没有此类成员或参数不匹配,则返回 false。

函数调用的返回值放在 ret 中。

三、非静态成员函数

1、QMetaClassInfo classInfo(int index)

返回具有给定索引的类信息项的元数据。

class Widget : public QWidget
{
Q_OBJECT
Q_CLASSINFO("作者", "张三")
Q_CLASSINFO("时间", "2020-1-1")
......
};

QMetaClassInfo info = this->staticMetaObject.classInfo(0);
qDebug()<<info.name()<<info.value()<<(info.enclosingMetaObject() == this->metaObject());//作者 张三 true

2、int classInfoCount()

返回此类中类信息的项数。

3、int classInfoOffset()

返回此类的类信息偏移量,即该类第一个类信息项的索引位置。

如果类没有包含类信息的超类,则偏移量为0;否则,偏移量是类超类中所有类信息项的总和。

class Widget : public QWidget
{
Q_OBJECT
Q_CLASSINFO("作者", "张三")
Q_CLASSINFO("时间", "2020-1-1")
........
};

class Widget_child : public Widget
{
Q_OBJECT
Q_CLASSINFO("此类作者", "李四")
public:
Widget_child(QWidget *parent = nullptr);
};

Widget_child::Widget_child(QWidget *parent)
:Widget(parent)
{
qDebug()<<this->staticMetaObject.classInfoOffset();//2
}

4、const char * className()

返回类名。

5、int indexOfClassInfo(const char *name)

查找类信息项名称并返回其索引,没有这个名词的类信息项则返回-1。

class Widget : public QWidget
{
Q_OBJECT
Q_CLASSINFO("作者", "张三")
Q_CLASSINFO("时间", "2020-1-1")
......
};

qDebug()<<this->staticMetaObject.indexOfClassInfo("时间");//1

6、int constructorCount()

返回此类中构造函数的数目。构造函数加上 Q_INVOKABLE 宏才能被元对象系统识别。

class Widget : public QWidget
{
Q_OBJECT

public:
Q_INVOKABLE Widget(QWidget *parent = nullptr);
~Widget();

......

7、QMetaMethod constructor(int index)

返回具有给定索引的构造函数的元数据。

8、int indexOfConstructor(const char *constructor)

查找构造函数并返回其索引,找不到则返回 -1。

构造函数必须是规范化的形式,如 normalizedSignature() 返回的那样。

void Widget::on_pushButton_clicked()
{
auto metaObject = this->staticMetaObject;
qDebug()<<metaObject.indexOfConstructor(QMetaObject::normalizedSignature("Widget()"));
}

9、int enumeratorCount()

返回此类中的枚举数。枚举加上 Q_FLAG() 才能被元对象系统识别。

enum test01
{
};
Q_FLAG(test01)

enum class test02
{
};
Q_FLAG(test02)

qDebug()<<this->staticMetaObject.enumeratorCount();//2

10、QMetaEnum enumerator(int index)

返回具有给定索引的枚举的元数据。

11、int enumeratorOffset()

返回此类的枚举偏移量,即此类第一个枚举的索引位置。

如果类没有带枚举的超类,则偏移量为0;否则,偏移量是类超类中所有枚举数的总和。

12、int indexOfEnumerator(const char *name)

查找枚举并返回其索引,找不到则返回 -1。

13、QMetaMethod method(int index)

返回具有给定索引的方法的元数据。加上 Q_INVOKABLE 宏的方法才能被元对象系统识别。

14、int methodCount()

返回此类中的方法数,包括所有基类提供的方法数。这包括了信号和槽。

获取包含特定于给定类的方法:

const QMetaObject* metaObject = obj->metaObject();
QStringList methods;
for(int i = metaObject->methodOffset(); i < metaObject->methodCount(); ++i)
methods << QString::fromLatin1(metaObject->method(i).methodSignature());

15、int indexOfMethod(const char *method)

查找函数并返回其索引,找不到则返回 -1。

method 必须是规范化的形式,如由 normalizedSignature() 返回。

void Widget::on_pushButton_clicked()
{
auto metaObject = this->staticMetaObject;
qDebug()<<metaObject.indexOfMethod(QMetaObject::normalizedSignature("on_pushButton_clicked()"));
}

16、int methodOffset()

返回此类的方法偏移量,即该类第一个成员函数的索引位置。

偏移量是类的超类中所有方法的总和。

17、int indexOfSignal(const char *signal)

查找信号并返回其索引,找不到则返回 -1。

这与 indexOfMethod() 相同,只是如果方法存在但不是信号则将返回 -1。

signal 必须是规范化的形式,如由 normalizedSignature() 返回。

18、int indexOfSlot(const char *slot)

查找槽并返回其索引,找不到则返回 -1。

这与 indexOfMethod() 相同,只是如果该方法存在但不是槽则将返回-1。

19、QMetaProperty property(int index)

返回具有给定索引的属性的元数据。属性使用 Q_PROPERTY 宏定义。

20、int indexOfProperty(const char *name)

查找属性并返回其索引,找不到则返回 -1。

class Widget : public QWidget
{
Q_OBJECT
Q_PROPERTY(int test READ getTest WRITE setTest NOTIFY testChanged)
......
};

auto metaObject = this->staticMetaObject;
qDebug()<<metaObject.indexOfProperty("test");

21、int propertyCount()

返回此类中的属性数,包括所有基类提供的属性数。

获取包含特定于给定类的属性:

const QMetaObject* metaObject = obj->metaObject();
QStringList properties;
for(int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i)
properties << QString::fromLatin1(metaObject->property(i).name());

22、int propertyOffset()

返回此类的属性偏移量,即此类第一个属性的索引位置。偏移量是类的超类中所有属性的总和。

23、bool inherits(const QMetaObject *metaObject)

当前 QMetaObject 描述的类是否继承 metaObject 所描述的类型。类型被视为继承自身。

24、QMetaType metaType()

返回与此元对象对应的元类型。

namespace test
{
class testClass : public QObject
{
Q_OBJECT
public:
testClass() = default;
};
}

class Widget : public QWidget
{
Q_OBJECT

......
};


void Widget::on_pushButton_clicked()
{
qDebug()<<this->staticMetaObject.metaType().name(); //Widget
test::testClass t1;
qDebug()<<t1.staticMetaObject.metaType().name(); //test::testClass
}

25、QObject * newInstance(QGenericArgument val0 = QGenericArgument(nullptr), QGenericArgument val1 = QGenericArgument(), ......)

构造此类的新实例。最多可以向构造函数传递十个参数(val0、val1、val2、val3、val4、val5、val6、val7、val8、val9)。

返回新对象,如果没有合适的构造函数,则返回nullptr。

要注意只有使用 Q_INVOKABLE 宏声明的构造函数才能通过元对象系统使用。

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Widget w;
// w.show();
if(Widget * w = qobject_cast<Widget*>(Widget::staticMetaObject.newInstance()))
{
w->show();
}

return a.exec();
}

26、const QMetaObject * superClass()

返回超类的元对象,如果没有此类对象,则返回nullptr。

27、QMetaProperty userProperty()

返回 USER 标志设置为 true 的属性。见:Qt属性系统。

四、宏成员

1、QGenericArgument Q_ARG(Type, const Type &value)

此宏接受 Type 和对该类型值的常量引用,并返回可以传递给 QMetaObject::invokeMethod() 的 QGenericArgument 对象。

2、QGenericReturnArgument Q_RETURN_ARG(Type, Type &value)

此宏接受 Type 和对该类型值的非常量引用,并返回可以传递给 QMetaObject::invokeMethod() 的QGenericReturnArgument 对象。

免费学习C++ Qt开发教程视频,点击下面链接免费报名领取视频学习资料

C/C++项目实战/Qt5/C语言/c++/数据库/OpenCV/MFC/QT项目-学习视频教程-腾讯课堂

原文链接:https://blog.csdn.net/kenfan1647/article/details/127361199

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: