Qt之QObject

1.梗概
    QObjects会自我构建对象树,当你创建一个以另一个对象作为父对象的QObject对象时,它被加到父对象的children()列表中,同时当父对象被删除时其也被删除,这被证明是非常适应GUI的应用需求。例如,QShortcut是一个相关窗口的子对象,当用户关闭窗口时,shortcut也会被删除。

2.QObject构造/析构的次序
  当QObjects在堆上创建出来,对象树能够被以任意次序构建,在树上的对象能够以任意次序销毁。当任意在树上的QObject被销毁,假如对象有一个父对象,析构函数则自动的从其父对象中移除,假如该对象有子对象,则其析构函数会自动删除每个子对象,没有对象会被销毁2次,不管其析构的顺序是怎样。当QObjects在栈上创建,也是同样的套路,正常来说,析构的顺序依旧不是个问题;

int main()
{
	QWidget window;
	QPushButton quit("Quit",&window);
	...
}

  window 和quit子对象都是QObjects对象,因为QPushButton继承QWidget,QWidget继承继承自QObejct.quit的析构函数不会被调用两次,因为c++语言标准(ISO/IEC 14882:2003)指定本地对象的析构函数被以其构造函数的反向顺序。因此,quit子对象的析构函数第一个被调用,然后它在window的析构函数被调用之前从它的父对象window中移除。但是现在该考虑的是假如我们交换构造的顺序后会发生什么。

int main()
{
	QPushButton quit("Quit");
	QWidget window;
	
	quit.setParent(&window);
	...
}

  在这个案例中,析构的顺序引发一个问题,父对象的析构函数被第一个调用因为它是最后创建的,该对象接着调用它子对象quit的析构函数,但这是不对的,因为quit是个本地变量,当quit随后离开作用域后,他的析构函数将会被再次调用,这次是正确的吗,但是也造成了危害。

  总而言之,就Qt asistant中object tree&ownnership中的翻译来说,可以总结几点,(1)无论是堆还是在栈中,对象树都是可以被创建出来的;(2)在对象树中,对象的构造顺序是很重要的,这直接决定析构的顺序;

-----------------------------------------------------------------------------------------------------------------------------------------

资料来源:

https://www.cnblogs.com/zhying13/p/4020075.html

https://doc.qt.io/archives/qt-4.8/qobject.html#QObject

QObject :: QObject(QObject * parent = 0)

使用基类对象构造对象。

基类对象可以被视为派生类对象的所有者。例如,对话框是包含的“ 确定”和“ 取消”按钮的基类对象。基类对象的析构函数会破坏所有子对象

parent设置为0会构造一个没有父对象的对象。如果对象是窗口小部件,它将成为顶级窗口。

virtual QObject :: ~QObject()

销毁该对象,删除其所有子对象。

进出对象的所有信号都将自动断开,并且从事件队列中删除该对象的所有待处理发布事件。但是,使用deleteLater()通常更安全,而不是直接删除QObject子类。

警告:删除所有子对象。如果这些对象中的任何一个在堆栈或全局上,则程序迟早会崩溃。我们不建议从父项外部保留指向子对象的指针。如果您仍然这样做,则destroy()信号使您有机会检测对象何时被销毁。

警告:等待传递挂起事件时删除QObject可能会导致崩溃。如果QObject存在于与当前正在执行的不同的线程中,则不能直接删除它。改为使用deleteLater(),这将导致事件循环在所有挂起事件传递给它之后删除该对象。

----------------------------------------------------------------------------------------------------------------------------

 QObject 类是Qt 所有类的基类。

QObject是Qt对象模型的核心。这个模型的中心要素就是一种强大的叫做信号与槽无缝对象沟通机制。你可以用 connect()函数来把一个信号连接到槽,也可以用disconnect()函数来破坏这个连接。为了避免永无止境的通知循环,你可以用blockSignal()函数来暂时阻塞信号。保护函数connectNotify()和disconnectNotify()可以用来跟踪连接。

对象树都是通过QObject 组织起来的,当以一个对象作为父类创建一个新的对象时,这个新对象会被自动加入到父类的 children()队列中。这个父类有子类的所有权。能够在父类的析构函数中自动删除子类。可以通过findChild()和findChildren()函数来寻找子类。

  每个对象都一个对象名称objectName(),而且它的类名也可以通过metaObject()函数。你可以通过inherits()函数来决定一个类是否继承其他的类。当一个对象被删除时,它会发射destory()信号.你可以抓住这个信号避免某些事情。

  对象可以通过event()函数来接收事情以及过滤来自其他对象的事件。就好比installEventFiter()函数和eventFilter()函数。childEvent()函数能够重载实现子对象的事件。

QObject还提供了基本的时间支持,QTimer类 提高了更高层次的时间支持。

  任何对象要实现信号与槽机制,Q_OBJECT 宏都是强制的。你也需要在源原件上运行元对象编译器。不管是否真正用到信号与槽机制,最好在所有QObject子类使用Q_OBJECT宏,以避免出现一些不必要的错误。

所有的Qt widgets 都是基础QObject。如果一个对象是widget,那么isWidgetType()函数就能判断出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值