前言:
目前兄弟们对“类中的构造函数名字是______”大概比较关切,兄弟们都需要分析一些“类中的构造函数名字是______”的相关知识。那么小编也在网摘上收集了一些有关“类中的构造函数名字是______””的相关知识,希望我们能喜欢,姐妹们快快来了解一下吧!一、QObject的重要知识
QObject是Qt对象模型的核心。这个模型的核心特性是一个强大的无缝对象通信机制,即信号和槽。可以使用connect()将信号连接到槽函数,并使用disconnect()破坏已经存在的连接。为了避免永不结束的通知循环,可以使用blockSignals()暂时阻塞信号。受保护的函数connectNotify()和disconnectNotify()可以用于跟踪信号连接。
Qt中,以QObject为基础形成了一棵“对象树”,当使用另一个对象作为父对象创建QObject时,该对象将自动将自己添加到父对象的children()列表中。此后父对象拥有该对象的所有权,则会自动删除析构函数中的子元素。在开发中可以使用findChild()或findChildren()根据名称和可选的类型查找子对象。
每个对象都有一个objectName(),可以通过相应的metaObject()找到它的类名(函数:QMetaObject::className())。在实际开发中可以使用inherits()函数确定对象的类是否继承了QObject继承层次结构中的另一个类。当一个对象被删除时,会发出destroyed()信号,通过这一点可以捕获此信号,避免对QObject进行悬挂引用。
二、QObject重要成员函数
本小节总结在开发中,QObject中常使用的成员函数和重要宏定义。
1、事件获取和处理API
/* 在此对象上安装事件筛选器filterObj */void QObject::installEventFilter(QObject *filterObj) /* 这个虚拟函数接收对象的事件,如果事件e被识别并处理,则返回true */bool QObject::event(QEvent *e)2、对象的线程关联API
/* 返回对象所在的线程。 */QThread *QObject::thread() const /* 更改对象及其子对象的线程关联性。如果一个对象有父对象,则不能移动该对象到另一个线程中 */void QObject::moveToThread(QThread *targetThread)3、获取子对象API
/* 返回该对象具有给定名称的所有可转换为类型T的子对象,如果没有此类对象,则返回一个空列表 */QList<T> findChildren(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const /* 返回子对象列表 */const QObjectList & children() const4、qobject_cast
函数原型如下:
T qobject_cast(QObject* object)T qobject_cast(const QObject* object)
如果对象类型为T(或子类),则将给定的对象转换为类型T;否则返回nullptr。如果对象是nullptr,那么它也将返回nullptr。
注意:类T必须继承(直接或间接)QObject并使用Q_OBJECT宏声明。
qobject_cast()函数的行为类似于标准c++dynamic_cast(),它的优点是不需要RTTI(Run-Time Type Identification-运行时类型识别)支持,并且可以跨动态库边界工作。
5、事件处理相关函数
//此虚函数用于接收对象的事件,如果事件e被识别和处理,则返回true。virtual bool event(QEvent *e)//如果此对象已作为被监视对象的事件过滤器安装,则过滤事件。virtual bool eventFilter(QObject *watched, QEvent *event)//从该对象中移除事件筛选器对象obj。void removeEventFilter(QObject *obj)//在对象上安装事件筛选器filterObjvoid installEventFilter(QObject *filterObj)6、定时器相关函数
//启动计时器并返回计时器标识符int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)//启动计时器并返回计时器标识符int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer)//使用定时器标识符id终止计时器void killTimer(int id)7、重要宏定义Q_DISABLE_COPY(Class)禁止对给定类使用复制构造函数和赋值运算符。Q_DISABLE_COPY_MOVE(Class)
该宏用于禁用给定类的复制构造函数、赋值运算符、移动构造函数和移动赋值运算符,将Q_DISABLE_COPY和Q_DISABLE_MOVE组合在一起。
Q_DISABLE_MOVE(Class 5.13)
禁止对给定类使用移动构造函数和移动赋值操作符。
Q_EMIT
当希望使用第三方信号/槽函数机制来使用Qt信号和槽函数时,可以使用此宏替代emit关键字来发出信号。
Q_ENUM(...)
这个宏用于向元对象系统注册一个枚举类型。该宏必须放在enum声明之后,且放在具有Q_OBJECT或Q_GADGET宏的类中。对于命名空间,应该使用Q_ENUM_NS()。例如:
class MyClass : public QObject{ Q_OBJECTpublic: MyClass(QObject *parent = nullptr); ~MyClass(); enum Priority { High, Low, VeryHigh, VeryLow }; Q_ENUM(Priority) void setPriority(Priority priority); Priority priority() const;};Q_ENUM_NS(...)
这个宏向元对象系统注册一个枚举类型。它必须放在enum声明之后,,且具有Q_NAMESPACE宏的名称空间中。与Q_ENUM相同,但在命名空间中。
Q_FLAG(...)
这个宏向元对象系统中注册一个单标记类型。它通常用于类定义中,以声明给定enum的值可以用作标志,并使用按位或运算符进行组合。对于命名空间,应该使用Q_FLAG_NS()。例如:
class QLibrary : public QObject{ Q_OBJECTpublic: ... enum LoadHint { ResolveAllSymbolsHint = 0x01, ExportExternalSymbolsHint = 0x02, LoadArchiveMemberHint = 0x04 }; Q_DECLARE_FLAGS(LoadHints, LoadHint) Q_FLAG(LoadHint) ...}Q_INTERFACES(...)
这个宏告诉Qt这个类实现了哪些接口。在宏定义在实现插件的时候使用。例如:
class BasicToolsPlugin : public QObject, public BrushInterface, public ShapeInterface, public FilterInterface{ Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" FILE "basictools.json") Q_INTERFACES(BrushInterface ShapeInterface FilterInterface)public: ...};Q_NAMESPACE
Q_NAMESPACE宏用于将QMetaObject功能添加到名称空间。Q_NAMESPACE可以有Q_CLASSINFO、Q_ENUM_NS、Q_FLAG_NS,但不能有Q_ENUM、Q_FLAG、Q_PROPERTY、Q_INVOKABLE、信号或槽函数。
Q_NAMESPACE_EXPORT(EXPORT_MACRO)
该宏的工作原理与Q_NAMESPACE宏完全相同。但是,在名称空间中定义的外部staticMetaObject变量是用提供的EXPORT_MACRO限定符声明的。如果需要从动态库导出对象,该宏定义非常有用。
Q_OBJECT
Q_OBJECT宏必须出现在类定义的私有部分中,该类定义声明自己的信号和槽函数,或者使用Qt元对象系统提供的其他支持。
Q_PROPERTY(...)
此宏用于在继承QObject的类中声明属性。属性的行为类似于类数据成员,但它们具有可通过元对象系统访问的其他特性。如下代码:
Q_PROPERTY(type name (READ getFunction [WRITE setFunction] | MEMBER memberName [(READ getFunction | WRITE setFunction)]) [RESET resetFunction] [NOTIFY notifySignal] [REVISION int] [DESIGNABLE bool] [SCRIPTABLE bool] [STORED bool] [USER bool] [CONSTANT] [FINAL])Q_SIGNAL
这是一个额外的宏,允许我们将单个函数标记为信号。当使用不支持信号或Q_SIGNALS组的第三方源代码解析器时,使用这个宏。
Q_SLOT
这是一个额外的宏,它允许将单个函数标记为槽函数。当使用不支持槽函数或Q_SLOT组的第三方源代码解析器时,使用这个宏。
三、信号和槽的连接机制注意事项
1、【自动连接(默认)】如果信号是在接收对象具有关联的线程中发出的,那么行为与直接连接相同。否则,行为与队列连接相同。
2、【直接连接】当信号发出时,槽函数被立即调用。槽函数在发射器的线程中执行,而发射器的线程不一定是接收器的线程。
3、【队列连接】当控制返回到接收方线程的事件循环时调用槽,槽函数在接收方的线程中执行。
4、【阻塞排队连接】槽被调用为排队连接,除非当前线程阻塞直到槽函数返回。
注意:使用该阻塞排队连接类型连接同一线程中的对象将导致死锁。
5、【唯一连接】与自动连接相同,但只在不复制现有连接的情况下才建立连接。也就是说,如果相同的信号已经为相同的对象连接到相同的槽,那么就不创建连接,并且connect()返回false。
连接类型可以通过向connect()传递一个附加参数来指定。注意,如果事件循环运行在接收方的线程中,当发送方和接收方位于不同线程中时使用直接连接是不安全的,这与调用位于另一个线程中的对象上的函数是不安全的原因相同。
QObject::connect()本身是线程安全的。
对于队列连接,传递的参数必须是Qt元对象系统已知的类型,因为Qt需要复制参数,以便存储参数;如果参数类型不是Qt元对象系统已知的,使用队列连接,将获得错误提示信息,这时候则需要在创建连接之前,调用qRegisterMetaType()向元对象系统注册该数据类型。
四、线程关联性
在Qt中,QObject实例具有线程相关性,或者可以理解成QObject存在于某个线程中。当QObject接收到排队的信号或发布的事件时,槽函数或事件处理程序将在该对象所在的线程中运行,这一点很重要。
注意:如果一个QObject没有线程关联(也就是说,如果thread()返回0),或者如果它存在于一个没有运行事件循环的线程中,那么它就不能接收排队的信号或发布的事件。
默认情况下,QObject实例存在于创建它的线程中,在实际开发中可使用thread()查询对象的线程关联,并使用moveToThread()更改对象的线程关联。
注意:所有QObject必须与它们的父对象生活在同一个线程中。除此之外,还需要知道:
(1)如果涉及的两个QObject位于不同的线程中,setParent()将失败。
(2)当一个QObject被移动到另一个线程时,它的所有子线程也会被自动移动。
(3)如果QObject有一个父对象,moveToThread()将失败。
(4)如果QObject是在QThread::run()中创建的,它们不能成为QThread对象的子对象,因为QThread并不存在于调用QThread::run()的线程中。
QObject的父子关系必须通过传递一个指向子构造函数的指针或调用setParent()来设置。如果没有这个步骤,当调用moveToThread()时,对象的成员变量将保持在旧线程中。
『参考链接』:
【1】
【2】
标签: #类中的构造函数名字是______