QT常见面试题总结

1.QT中的内存管理机制

答:1)QT使用对象父子关系进行内存管理。在创建对象时候,指定父对象指针,当父对象被销毁的时候,父对象会先编译子对象,并逐个销毁子对象,最后在销毁父对象。2)使用引用计数进行对象内存管理,智能指针,QSharedPointer,此类是模板类,可以指向很多数据类型,主要用来管理内存,类似于C++中的shared_ptr。还有QWeakPointer,此类也是模板类,次指针智能从QSharedPointer指针进行初始化,不增加引用计数,只是QSharedPointer指针的观察者,观察而不干预。3)局部指针,是一种超出作用域自动删除、释放堆内存、对象的工具,比如QScopedPointer, QScopedArrayPointer。4)QT中的观察者指针是QPointer,必须指向QObject类型的子对象,因为只有QObject子对象在析构的时候通知QPointer已失效。

2.QT中的信号与槽的原理

答:1)如下图所示,信号是当一个对象的内部状态发生改变时候,如果其他对象对它的状态改变需要作出反应,这时候就需要让这个类发出状态改变的信号。声明信号使用signals关键字,发出信号使用emit关键字。信号的注意点,第一,所有的信号都是公开的,所以QT不能在信号声明的前面上public、private、或者protected。第二,信号都没有返回值,所以使用的是void。第三,所有的信号都不需要定义,只需要声明即可。第四,必须直接或者间接继承QObject类,并且开头私有声明中包含Q_OBJECT宏。第三,在一个线程中,当一个信号被emit发出时候,会立即执行槽函数,等待槽函数执行完毕后才执行emit后的代码。如果一个信号连接了多个槽,那么会等所有槽函数执行完毕后在执行emit后的代码,槽函数的执行顺序是按照其connect顺序的;不同线程中,参函数执行顺序是随机的。第六,在连接信号与槽函数时候,可以指定emit之后代码的执行时机的,按照connect的第五个参数控制的。第七,信号与槽机制要求参数类型一致。

2)槽:槽函数其实就是普通的C++函数,可以是虚函数、static函数,可以被重载,可以被访问修饰符修饰,也可以被其他C++成员函数调用等,它唯一的特定就是可以和信号连接。当与它连接的信号被emit时候,槽函数会被调用,槽必须直接或者间接继承QObject类型,然后声明Q_OBJECT宏。而且还可以使用Lambda表达式作为槽函数。

3)信号与槽的链接函数声明如下所示

static QMetaObject::Connection connect(

const QObject *sender, // 信号发送对象指针

const char *signal, // 信号函数字符串,使用SIGNAL()

const QObject *receiver, // 槽函数对象指针

const char *member, // 槽函数字符串,使用SLOT()

Qt::ConnectionType = Qt::AutoConnection);

connect(pushButton, SIGNAL(clicked()), dialog, SLOT(close())) 或者

connect(pushButton, &QPushButton::clicked, dialog, QDialog::close)

4)moc预编译器(Meta-Object Compiler):moc读取一个C++头文件。如果找到包含Q_OBJECT宏的一个或多个类声明,它会生成一个包含这些类的元对象代码的C++源文件,并且已moc_作为前缀。信号和槽机制、运行时类型信息和动态属性系统需要原对象代码。如下图所示,当定义Q_OBJECT宏时候意味着定义如下的内容。

5)信号与槽的具体流程:第一,moc查找头文件中的signals和slots,标记出信号和槽。第二,将信号与槽信息存储到类的静态变量staticMetaObject中,并且按照声明顺序进行存储,建立索引。第三,当发送有connect连接时候,将信号与槽的索引信息放到一个map中,彼此配对。第四,当调用emit时候,调用信号函数,并且传递发送信号的对象的指针,元对象指针,信号索引,参数列表到active函数中。第五,通过active函数在map中找到所有与信号对应的槽索引。第六,根据槽索引找到槽函数,然后执行槽函数。

6)槽是有访问修饰符的,当slots被public修饰的时候,意味着槽可以被所有信号连接;当slots被protected修饰时候,意味着槽只能与当前类和其子类的信号连接;当slots被private修饰的时候,意味着槽只能和当前类的信号连接。

7)信号和槽定义的时候需要注意的问题:第一,不能在信号和槽参数中存在宏定义,因为moc是不展开宏的。第二、构造函数是不能用于信号槽声明区域中。第三,函数模板是不能用于信号和槽的参数的。第四,信号和槽不能有缺省参数。第五,函数指正不能作为信号或者槽的参数。

3.Qt中的事件过滤器()eventFilter)详解

答:在Qt中,event被建模成派生自abstract QEvent类的对象,用来表示在应用程序中发生的事件,或是应用程序需要处理的外部活动产生的事件。Events可以被任何QObject派生类对象接收和处理。

1)event是如何发送的:通常情况下,当一个事件发生的时候, Qt 通过构造一个合适的 QEvent子类对象来表示事件的发生, 然后将该事件对象发送给特定的 QObject对象( 或其子类实例对象), 通过调用该 QObject 的 event() 函数. 这个 event() 函数不会对事件本身进行处理, 而是首先检查所接受到event 的类型, 然后根据 event 的类型来调用相应的 event handler, event handler 在处理完 event 之后会返回一个bool值表示 该 event是被接受了,还是被忽略了。某些事件, 例如 QMouseEvent 和 QKeyEvent, 来自于窗口系统; 某些, 例如 QTimerEvent, 来自于其他的事件源; 某些, 来自于应用程序本身.

2)event类型:Qt为多数 Event 类型建立了相应的类, 常见有QResizeEvent, QPaintEvent, QMouseEvent, QKeyEvent, QCloseEvent.每一个特定的 event 类都是继承自 QEvent 基类,添加特定的事件函数. 例如, QResizeEvent 添加了 size() 和 oldSize() 让控件可以发现他们的尺度,发生了的怎么改变.某些类实际支持不止一种事件类型. QMouseEvent 就支持鼠标按键按下事件,双击事件, 移动事件, 以及其他相关操作所引发的事件.每一个事件都有它的类型, 由 QEvent::Type 定义, 运行时可以很方便的检测每个事件对象的事件类型,以快速的判断该事件对象构造自哪个事件类.

4.Qt中如何进行多线程编程

答:1) 继承QThread类:可以创建一个类型,继承QThread类,实现其run方法,在run方法内部实现业务逻辑处理。然后创建该类型的对象,调用其start函数创建子线程并执行。2) 使用线程池QtConcurrent框架:QtConcurrent框架提供了一组更高级的类和函数,用于简化多线程编程,例如可以使用QFture和QFutureWatcher类来管理并发任务的执行和结果获取。线程池中的任务必须是QRunnable类型。

3)使用Qt的信号槽机制。4)随便写一个继承QObject类的类,然后创建一个对象,然后创建一个QThread线程对象,然后调用对象的->moveToThread(子线程指针)这样就这个对象丢到了子线程中去运行,然后再让线程start。5)QThreadPool全局的线程池实例对象。

5.Qt中的网络编程,网络通信的方法和相关类

答:1)在.pro文件中要添加qt+=network,否则无法启用Qt的网络编程功能。2)Qt中通过QTcpSocket和QTcpServer类实现TCP网络通信,UDP通信。

3)TCP通信的流程:创建套接字服务器QTcpServer对象;通过QTcpServer对象设置监听,即QTcpServer::listen();基于QTcpServer::newConnection()函数检测是否有新的客户端连接;如果有新的客户端连接,调用QTcpSocket *QTcpServer::nextPendingConnection()得到通信的套接字对象;使用通信的套接字对象QTcpSocket和客户端通信。

4)在QT中使用了多线程,这些事是需要额外注意的:默认的线程在QT中称之为窗口线程,也叫做主线程或者GUI,负责窗口事件处理或者窗口空间数据的更新,子线程负责后台的业务逻辑处理,子线程中不能对对象做任何操作,这些事情需要交给窗口线程处理,主线程和子线程之前需要进行数据的传递,需要使用QT中的信号槽机制。

6.Qt的国际化和本地址支持,如何在Qt程序中实现多语言支持。

答:1)在做项目时候,我们希望我们的程序可以在不同的国家中使用,这样最好的方式就是一套程序能适用于多国语言,Qt就提供了这样的一种能力,使得一套程序可以呈现出不同的语言和界面。Qt提供了强大的国际化(Internationalization)和本地化(Localization)支持,使开发者将能够轻松地将应用程序适用不同的语言的地区。

2)国际化和本地化:国际化是指将应用程序设计成可以轻松适应不同的一眼和地区的能力,而本地化则是根据特定的语言和地区要求进行适配和翻译。Qt提供了一系列的工具和类来支持国际化和本地化,包括支持多语言字符串的翻译、日期和时间格式化,货币和数字格式化、Unicode支持等。

3)Qt在应用程序中支持多语言的步骤如下所示:

11)提供翻译文件,需要为每一种语言准备翻译文件,这些文件包含应用程序中所有需要翻译的字符串。翻译文件以.ts结尾。

22)提取可翻译字符串,使用Qt的国际化工具Linguist或者命令行工具Lupdate扫描应用程序的源代码和资源文件,提取可翻译的字符串生成对应的翻译文件(.ts文件)。

33)进行翻译,将生成的翻译文件交给翻译团队进行翻译工作,翻译人员可以使用Qt的国际化工具Linguist来打开翻译文件,并在其中提供对应语言的翻译。

44)编译翻译文件:使用Qt的国际化工具(Linguist)或命令行工具(lrelease)编译翻译文件,生成对应语言的二进制翻译文件(.qm文件)。这些二进制文件包含了翻译的字符串以及其对应的上下文信息,可以在运行时加载和使用。

55)加载和使用翻译文件,在应用程序中加载适当的翻译文件,通常是根据客户的首选语言或者应用程序的配置来确定,一旦加载了翻译文件,Qt会自动翻译的字符串应用到响应的界面元素的文本中。

66)动态切换语言:如果应用程序需要支持动态切换语言,可以通过重新加载新的翻译文件来实现。Qt提供了QTranslator类,可以用于加载和切换翻译文件。通过在应用程序中维护一个翻译器对象,并在需要切换语言时重新加载对应的翻译文件,可以实现动态切换语言的功能。

77)文本国际化:Qt提供了一系列用于本地化文本的类和函数。例如,QCoreApplication类提供了一些静态函数,如tr()和trUtf8(),用于将字符串进行翻译。这些函数接受一个标识符作为参数,根据当前加载的翻译文件将其翻译成对应语言的文本。

88)数字和日期的本地化:Qt提供了QLocale类,用于处理数字、日期和货币的本地化。QLocale可以根据当前语言环境提供正确的数字和日期格式,以及货币符号和货币格式。

99)常用控件的本地化支持:Qt的常用控件如QPushButton、QLabel等已经内置了对本地化的支持。这些控件会自动根据当前的翻译文件来显示相应的文本,从而实现多语言界面

7.Qt开发过程中,你是如何调试错误和排查错误的。

答:

1)调试器(Debugger):Qt集成了调试器支持,可以与各种调试器(如GDB)进行交互。通过在开发环境中设置断点、观察变量和执行步骤,可以逐步调试代码并查找问题。调试器允许我们在运行时检查应用程序的状态和执行流程,定位错误的具体位置。2)qDebug() 和 qWarning():Qt提供了QDebug类和qWarning()函数,可以输出调试信息和警告消息。这些信息对于追踪程序执行过程中的状态和数据很有帮助。通过在关键位置插入qDebug()或qWarning()语句,我们可以打印变量的值、函数的调用信息等,以帮助我们理解代码的执行流程和定位问题。3)Qt Creator集成调试工具:Qt Creator是Qt官方推荐的集成开发环境(IDE),它集成了强大的调试工具。通过使用Qt Creator,我们可以直观地设置断点、单步调试代码、查看变量的值和执行堆栈等。Qt Creator还提供了可视化的调试界面,使得调试过程更加方便和直观。4)内存泄漏检测:Qt提供了一些工具和技术来检测和解决内存泄漏问题。例如,通过重载对象的构造函数和析构函数,并使用Qt的内存管理类(如QSharedPointer、QScopedPointer)来管理对象的生命周期,可以避免内存泄漏。此外,Qt还提供了内存泄漏检测工具,如Valgrind,可以帮助我们发现和修复潜在的内存泄漏问题。5)日志记录:在开发过程中,使用日志记录是一种有用的调试和错误排查技术。Qt提供了QLoggingCategory类和qInstallMessageHandler()函数,可以帮助我们将日志消息输出到文件或控制台。通过在关键位置添加日志记录语句,并根据需要调整日志级别,可以获取应用程序运行时的详细信息,从而帮助我们分析问题和进行错误排查。

8.Qt中的最佳实践和设计原则。

答:

1)采用MVC架构,将界面、数据、业务处理分离,以便于进行单独的管理和测试。2)尽量使用Qt提供的标准控件和布局管理器,这样可以减少自定义控件的工作量,同时保证应用程序的一致性。3)将程序分解成小模块,每个模块负责独立的功能,并且模块直接的接口要尽量简单清晰。4)采用良好的命名规范,命名要简单清晰明了释义。5)使用Qt的信号好槽机制,可以简化代码的编写,增加程序的可读性和可维护性。6)采用RAII原则,在构造函数中获取资源,在析构函数中释放资源,保证资源正确释放。7)使用Qt的工具和技术,如Qt Creator等。8)使用版本控制工具,比如Git SVN等,可以方便地管理和追踪代码的变化。9)进行良好的文档注释,方便代码开发和维护。

9、QT拖放介绍

答:1)拖放描述了一种简单的可视化机制,用户可以使用该机制在应用程序之间和应用程序内部传递消息。拖放功能类似于剪贴板的剪贴和黏贴机制。Qt的许多空间以及QtWidgests和Qt Quick的编辑空间也支持拖放操作。

2)拖放相关的类:QDrag(支持基于MIME的拖放的数据传输),QDragEnterEvent(拖放进入事件,拖放动作进入小部件时候发送给小部件的事件),QDragLeaveEvent(拖动离开事件,拖放操作离开小部件时候发送给小部件的事件),QDradMoveEvent(拖动移动事件,拖放进入小部件后移动时候发送给小部件的事件),QDragEvent(拖动放下事件,拖放动作完成时候发送的事件)。

10、Qt线程同步的方法

答:1)QMutex类就像一把锁,在互斥量上锁(lock()),使用完之后释放锁(unlock()).

2)QMutextLocker便利类,可以使用其对互斥量进行简化处理,首先,QMutexLocker类接收一个QMutex作为参数并上锁,然后在析构函数中自动对其进行解锁。

3)QReadWriteLock锁,这个锁可以对线程的操作进行分类,读和写。lockforRead()/lockForWrite() unlock()。

4)QReadLocker和QWriteLocker便利类。

5)信号量Qsemaphore。

6)条件触发QWaitCondition。

全部评论

相关推荐

8 83 评论
分享
牛客网
牛客企业服务