目录
1、怎么在QT中添加源代码,可以直接查看相关源代码
这个是相关衔接,我在网上找的,已经实验成功,讲的也很清楚,如果不同意我发送衔接,文章作者可以联系我,我立马删除,在Qt creator中查看Qt源码_qt源码在哪儿-CSDN博客
2、为什么要将这个QT的基类讲一讲
主要是因为在学习代码的过程中,看大神的源码能够让你进步,可能大家都在写代码,也都实现了某个功能,但是一涉及改需求,很多人代码改动特别大,根本就不会封装,代码的规范性极差,将代码写规范,区分模块化功能,都是必学的,千万不要妄自菲薄,也不要自恃其高,觉得实现功能就好,对于积压的垃圾山代码视而不见。
可能很多人都说,大家都要生活,大差不差就好,浪费自己的时间何必呢,逐渐的,时间一天一天过,你会对写代码变得麻木,当你不在热爱写代码,你会厌恶它,觉得恶心,逐渐对它失去热情。
计算机这个行业更迭太快,秉承着开源的精神,有利也有弊,它进化的太快,几乎可以为所有行业赋能,同时它也在抛弃那些停滞不前的人。
残酷且现实。
但是,
唯有一句我想对所有人说:唯有热爱,可抵岁月漫长。
3、代码的规范性问题
在我刚进公司写代码的那段时间,我可以说是为了实现功能,随心所欲的写代码,当时也在看公司老程序的代码,说实话,有些老程序的代码真的屎山,但是可以完美运行,所以开始的一个月除了帮忙改bug,我就一直在看公司的代码,作为公司的老项目代码,一个cpp就6000多行,可以说是很不规范,但是没有办法,只能一点点的看,6000多行我硬是看完了,虽然有很多不规范,但是也学到了很多。
写的代码越多,越发觉得QT的代码真的很优雅,高级。
很喜欢QT,它简化了学习c++的难度,很多东西都帮你封装好了,很妙。
4、关于QObject的认识以及使用
在Qt框架中,QObject类是所有Qt对象的基类,它提供了一些基本功能,包括:
-
信号和槽机制(Signals and Slots):QObject通过信号和槽机制实现了对象间的通信。这种机制使得对象之间可以在事件发生时进行通信,而不需要直接调用彼此的方法。信号用于发出某种特定事件的通知,而槽则用于接收这些通知并执行相应的操作。
-
对象树结构管理:QObject支持对象树结构,可以方便地管理对象之间的父子关系。当一个QObject对象被指定为另一个QObject对象的子对象时,它将成为后者的子项,并且在后者被删除时会自动被删除。这种机制有助于管理内存,避免内存泄漏。
-
属性系统:QObject提供了一个属性系统,允许为对象定义和访问属性。这些属性可以是任何类型的数据,并且可以通过属性名称来访问。QObject属性系统也支持属性的通知机制,可以在属性值发生变化时发出信号。
-
事件处理:QObject提供了基本的事件处理功能,使得对象能够响应来自操作系统或其他对象的事件。它可以接收、过滤和处理事件,以便对象可以与用户交互或与其他对象进行通信。
5、查看QObject使用说明书
QObject是QT所有类的基类,
注意:All functions in this class are reentrant.
"All functions in this class are reentrant."这句话意味着该类中的所有函数都是可重入的。在多线程编程中,"可重入"是一个重要的概念。
可重入性指的是函数在同一时间可以被多个线程调用,而不会产生不正确的结果或者破坏数据结构的状态。具有这种特性的函数可以安全地在多线程环境中使用,而不需要额外的同步措施(如互斥锁)来保护其数据。
在实践中,函数如果满足以下条件之一,则被认为是可重入的:
- 不使用任何静态数据。
- 如果使用静态数据,所有使用的静态数据都是常量,或者被函数本身以及它调用的其他函数所独占使用,而不会被其他线程访问。
- 使用静态数据,但是在访问这些静态数据时使用了互斥锁或其他同步机制来确保线程安全。
如果一个类中的所有函数都是可重入的,那么这个类就被认为是可重入的。这意味着在多线程环境中,可以安全地同时调用该类的不同函数,而不必担心数据的一致性问题。这种情况下,通常不需要额外的同步机制来保护该类的对象。
总之,如果一个类中的所有函数都是可重入的,那么该类就具有更好的线程安全性,更容易在多线程环境中使用。
注意:
Note: These functions are also thread-safe:
这些函数被标记为线程安全是因为它们在多线程环境中可以安全地使用,而不需要额外的同步机制来保护它们。这样的设计使得在多线程程序中使用这些函数更加容易和安全。
关于更多的细节,可以在使用手册中查看。
6、关于connect的第五个参数
- connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
- connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
- connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type)
- connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
- connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type)
- disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
- disconnect(const char *signal, const QObject *receiver, const char *method) const
- disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)
- deleteLater()
-
这段注释说明了这些函数都是线程安全的。在多线程环境中,线程安全是确保并发执行时不会导致不正确的行为或数据损坏的性质。
下面是每个函数的简要说明:
-
connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
:用于在发送者对象的信号和接收者对象的槽函数之间建立连接。这个函数允许在不同线程中的对象之间建立连接,并且线程安全。 -
connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
:与上一个函数类似,但是接收者对象是当前对象的常量指针。这也是线程安全的。 -
connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type)
:用于连接通过指向成员函数的指针定义的信号和槽。这个函数也是线程安全的。 -
connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
:这个重载函数允许将信号连接到可调用对象(例如函数对象)上。也是线程安全的。 -
connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type)
:类似于上一个重载,但提供了额外的参数以指定连接的上下文对象。这个函数也是线程安全的。 -
disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
:用于断开发送者对象的信号和接收者对象的槽函数之间的连接。这个函数是线程安全的。 -
disconnect(const char *signal, const QObject *receiver, const char *method) const
:与上一个函数类似,但接收者对象是当前对象的常量指针。也是线程安全的。 -
disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)
:用于断开通过指向成员函数的指针定义的信号和槽之间的连接。这个函数也是线程安全的。 -
deleteLater()
:用于安全地延迟删除当前对象,通常在事件循环中使用。这个函数也是线程安全的。
在Qt中,QObject::connect()
函数的第五个参数是连接类型(ConnectionType),它指定了连接的行为。Qt提供了以下几种连接类型,每种连接类型都有不同的作用:
-
Qt::AutoConnection:
- 如果发送者和接收者在同一线程中,则等效于
Qt::DirectConnection
,否则等效于Qt::QueuedConnection
。 - 这种连接类型的作用是根据发送者和接收者的线程自动选择合适的连接类型。
- 如果发送者和接收者在同一线程中,则等效于
-
Qt::DirectConnection:
- 在调用
QObject::connect()
函数时,如果发送者和接收者位于同一线程,则直接调用接收者的槽函数;如果不在同一线程,则该连接会失败(不会进行跨线程调用)。 - 这种连接类型的作用是直接调用接收者的槽函数,不涉及事件循环,所以效率较高。
- 在调用
-
Qt::QueuedConnection:
- 无论发送者和接收者是否在同一线程,都会将信号的调用和槽函数的执行都放入接收者对象所在的线程的事件队列中,在事件循环中处理。
- 这种连接类型的作用是确保槽函数在接收者所在的线程中执行,适用于跨线程的信号和槽连接。
-
Qt::BlockingQueuedConnection:
- 类似于
Qt::QueuedConnection
,但是发送者在调用QObject::connect()
函数时会阻塞,直到接收者执行槽函数完毕。 - 这种连接类型的作用是确保槽函数的执行完毕后,发送者才能继续执行。
- 类似于
-
Qt::UniqueConnection:
- 当多次调用
QObject::connect()
函数时,确保同一个信号和槽函数的连接只建立一次,重复的连接会被忽略。 - 这种连接类型的作用是避免建立重复的连接,提高连接的效率和可维护性。
- 当多次调用
这些连接类型可以根据具体的需求选择,以实现不同的信号和槽的连接行为。在调用QObject::connect()
函数时,可以使用这些连接类型中的任意一种。
查阅QT的底层代码,找到它的的枚举:
enum ConnectionType {
AutoConnection,
DirectConnection,
QueuedConnection,
BlockingQueuedConnection,
UniqueConnection = 0x80
};
定义了一个名为 ConnectionType
的枚举,它包含了五种连接类型。每种连接类型都有不同的含义和作用。
-
AutoConnection:自动连接。根据发送者和接收者的线程自动选择合适的连接类型。如果发送者和接收者在同一线程中,则等效于
DirectConnection
,否则等效于QueuedConnection
。 -
DirectConnection:直接连接。如果发送者和接收者在同一线程中,则直接调用接收者的槽函数;否则,连接会失败。
-
QueuedConnection:队列连接。无论发送者和接收者是否在同一线程,都会将信号的调用和槽函数的执行都放入接收者对象所在的线程的事件队列中,在事件循环中处理。
-
BlockingQueuedConnection:阻塞队列连接。类似于
QueuedConnection
,但是发送者在调用QObject::connect()
函数时会阻塞,直到接收者执行槽函数完毕。 -
UniqueConnection:唯一连接。确保同一个信号和槽函数的连接只建立一次,重复的连接会被忽略。
这些连接类型用于指定 QObject::connect()
函数的第五个参数,以确定信号和槽之间的连接方式。默认情况下,如果不指定第五个参数,Qt::AutoConnection
将被用作默认连接类型。
更多具体可以在QT助手查看。