Qt 每日面试题 -8

时间:2024-10-13 20:08:09

71、了解Qt的QPointer吗?

  • QPointer只能用于指向QObject及派生类的对象。 当一个QObject或派生类对象被删除后,QPointer能自动将其内部的指针设置为0 ,这样在使用QPointer之前就可以判断一下是否有效。
  • QPointer对象超出作用域时,并不会删除它指向的内存对象。

72、了解Qt的QSharedPointer吗?

QSharedPointer用于实现数据的隐式共享。Qt中大量使用了隐式共享与写时拷贝技术,例如∶

QString str1 = "abc" ;
QString str2 = str1;
str2[2] = "x";

第二行执行完后,str2和str1指向同一片内存数据。第三句执行时,Qt会为str2的内部数据重新分配内存。这样做的好处是可以有效地减少大片数据拷贝的次数,提高程序的运行效率。

  • Qt中隐式共享和写时拷贝就是利用QSharedDataPointerQSharedData这两个类实现的。

73、详解Qt中的内存管理机制

  • 所有继承自QOBJECT类的类,如果在new的时候指定了父亲,那么它的清理时在父亲被delete的时候也会被delete,所以如果一个程序中,所有的QOBJECT类都指定了父亲,那么他们是会一级级的在最上面的父亲清理时被清理,而不用自己清理;

  • 程序通常最上层会有一个根的QOBJECT,就是放在setCentralWidget ( )中的那个QOBJECT,这个QOBJECT在new的时候不必指定它的父亲,因为这个语句将设定它的父亲为总的QAPPLICATION,当整个QAPPLICATION没有时它就自动清理,所以也无需清理。(这里QT4和QT3有不同,QT3中用的是setmainwidgeti函数,但是这个函数不作为里面QOBJECT的父亲,所以QT3中这个顶层的QOBJECT要自行销毁)。

  • 如果我自行delete掉这些QT接管负责销毁的指针了会出现什么情况呢,如果时这样的话,正常情况下QT的拥有这个对象的那个父亲会知道这件事情,它会直到它的儿子被你直接DELETE了,这样它会将这个儿子移出它的列表,并且重新构建显示内容,但是直接这样做时有风险的!

  • 当一个QOBJECT正在接受事件队列时如果中途被你DELETE掉了,就是出现问题了,所以QT中建议大家不要直接delete掉一个QOBJECT,如果一定要这样做,要使用QOBJECT的deleteLater()函数,它会让所有事件都发送完一切处理好后马上清除这片内存,而且就算调用多次的deletelater也不会有问题。

  • QT不建议在一个QOBJECT的父亲的范围之外持有对这个QOBJECT的指针,因为如果这样外面的指针很可能不会察觉这个QOBJECT被释放,会出现错误,如果一定要这样,就要记住你在哪这样做了,然后抓住那个被你违规使用的QOBJECT的destroyed()信号,当它没有时赶快置零你的外部指针。如果要这样在外部持有QOBJECT的指针,建议使用引用或者用智能指针,如QT就提供了智能指针针对这些情况。

  • QT中的智能指针封装为QPointer类,所有QOBJECT的子类都可以用这个智能指针来包装,很多用法与普通指针一样。

74、知道Qt事件机制有几种级别的事件过滤吗?能大致描述下吗?

根据对Qt事件机制的分析,我们可以得到5种级别的事件过滤方法,以功能从弱到强,排列如下:

  1. 重载特定事件处理函数.
    最常见的事件处理办法就是重载像mousePressEvent(), keyPressEvent(), paintEvent(这样的特定事件处理函数.

  2. 重载event()函数.
    通过重载event()函数,我们可以在事件被特定的事件处理函数处理之前像keyPressEvent()处理它.

  3. 在Qt对象上安装事件过滤器.
    安装事件过滤器有两个步骤:(假设要用A来监视过滤B的事件)首先调用B的instalEventFilter(const QObject *obj ),以A的指针作为参数.这样所有发往B的事件都将先由A的eventFilter()处理;然后,A要重载QObjectreventFilter()函数,在eventilter()中书写对事件进行处理的代码.

  4. 给QAppliction对象安装事件过滤器.
    一旦我们给qApp(每个程序中唯一的QApplic ation对象)装上过滤器,那么所有的事件在发往任何其他的过滤器时,都要先经过当前这个eventFilter().在debug的时候这个办法就非常有用,也常常被用来处理失效了的widget的鼠标事件.通常这些事件会被QApplication::notify()丢掉.

  5. 继承QApplication类并重载notify()函数.
    Qt是用 QApplication::notify()函数来分发事件的想要在任何事件过滤器查看任何事件之前先得到这些事件重载这个函数是唯一的办法.通常来说事件过滤器更好用一些,因为不需要去继承QApplication类.而且可以给QApplication对象安装任意个数的事件。

75、什么是Qml

  • QML是语言的名称(就像C++,那是一些其他的语言……),QML代表Qt Meta Language或Qt Modelling Language,是一种人机界面标记语言。
  • QtQuick是QML的一个工具包,允许用QML语言扩展图形界面(还有其他的QML工具包,有些是图形化的,如Sailfish Silica或BlackBerry Cascade,还有一些是非图形化的,如QBS
  • QtQuick 1.x变成了基于Qt4.X,使用QPainter/QGraphicsView API来吸引场景。QtQuick 2.x与Qt5.0—起推出,主要基于Scene Graph,这是一个openGLES2抽象层,经过了相当的优化。

76、strcpy / sprintf / memcpy.它们之间区别?

  1. 执行对象
    strcpy:字符串
    memcpy:可适用于任意数据类型
    sprintf :目的对象是字符串,源对象可以是字符串、也可以是任意基本类型的数据

  2. strcpy:不需要指定长度,它遇到被复制字符的串结束符"\IO"才结束memcpy()会完整的复制num个字节,不会因为遇到"0"而结束

77、面向对象三大特性以及C++成员函数

  • 面向对象的三大特性:
    1. 封装
    2. 继承
    3. 多态
  • 类的六个默认成员函数︰
    1. 构造函数
    2. 拷贝构造函数
    3. 析构函数
    4. 赋值操作符重载
    5. 取地址操作符重载
    6. const修饰的取地址操作符重载

78、使用样式表要注意的点

父控件采用样式表设置属性后,该属性会传递到其子控件上,除非子控件使用同样的方法修改属性。如∶利用样式表设置父控件最小高度为x,则子控件的最小高度也为x,即使用setFixHeight()修改也无法消除,只能通过样式表重新设置子控件的高度才有效。因此一般只对子控件使用样式设置

79、描述Windows下一个消息从触发到处理的整个路由过程

  • 应用程序启动,操作系统为程序创建一个对应的消息队列,用户对创建进行操作,产生一系列消息,操作系统首先捕捉到这些消息,将消息投递到对应的消息队列中,在应用程序中对应一个消息循环

  • 消息循环每次从消息队列中取出消息,取出的消息如果是虚拟键消息,会将其转换成标准消息,将转换的消息再次投递到消息队列,如果取出的是标准消息, 会将该消息发送给操作系统,操作系统会调用对应的窗口过程函数,下一窗口过程函数中对对应的消息进程处理.

80、QApplication的主要作用是什么?

QApplication对象管理QtGui应用程序的控制流程和主要的设置参数