//E:\Qt\qt-everywhere-src-6.2.1\qtbase\src\corelib\kernel\qobject.cpp:928QObject::QObject(QObject *parent):QObject(*new QObjectPrivate, parent){}QObject::QObject(QObjectPrivate &dd, QObject *parent):d_ptr(&dd){Q_ASSERT_X(this!= parent, Q_FUNC_INFO,"Cannot parent a QObject to itself");Q_D(QObject);
d_ptr->q_ptr =this;auto threadData =(parent &&!parent->thread())? parent->d_func()->threadData.loadRelaxed():QThreadData::current();
threadData->ref();
d->threadData.storeRelaxed(threadData);if(parent){
QT_TRY {if(!check_parent_thread(parent, parent ? parent->d_func()->threadData.loadRelaxed():nullptr, threadData))
parent =nullptr;if(d->isWidget){if(parent){
d->parent = parent;//记录父指针
d->parent->d_func()->children.append(this);//加入到父对象的children列表}// no events sent here, this is done at the end of the QWidget constructor}else{setParent(parent);//设置parent,后面会展开}}QT_CATCH(...){
threadData->deref();
QT_RETHROW;}}#ifQT_VERSION <0x60000qt_addObject(this);#endifif(Q_UNLIKELY(qtHookData[QHooks::AddQObject]))reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);Q_TRACE(QObject_ctor,this);}
//E:\Qt\qt-everywhere-src-6.2.1\qtbase\src\corelib\kernel\qobject.cpp:2096voidQObjectPrivate::deleteChildren(){Q_ASSERT_X(!isDeletingChildren,"QObjectPrivate::deleteChildren()","isDeletingChildren already set, did this function recurse?");
isDeletingChildren =true;// delete children objects// don't use qDeleteAll as the destructor of the child might// delete siblingsfor(int i =0; i < children.count();++i){
currentChildBeingDeleted = children.at(i);
children[i]=nullptr;delete currentChildBeingDeleted;}
children.clear();
currentChildBeingDeleted =nullptr;
isDeletingChildren =false;}
voidQObject::setParent(QObject *parent){Q_D(QObject);Q_ASSERT(!d->isWidget);
d->setParent_helper(parent);}voidQObjectPrivate::setParent_helper(QObject *o){Q_Q(QObject);Q_ASSERT_X(q != o, Q_FUNC_INFO,"Cannot parent a QObject to itself");//不能设置QObjct的parent为自身#ifdefQT_DEBUGconstauto checkForParentChildLoops =qScopeGuard([&](){int depth =0;auto p = parent;while(p){if(++depth == CheckForParentChildLoopsWarnDepth){qWarning("QObject %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; ""this is undefined behavior",
q, q->metaObject()->className(),qPrintable(q->objectName()));}
p = p->parent();}});#endifif(o == parent)return;if(parent){
QObjectPrivate *parentD = parent->d_func();if(parentD->isDeletingChildren && wasDeleted
&& parentD->currentChildBeingDeleted == q){// don't do anything since QObjectPrivate::deleteChildren() already// cleared our entry in parentD->children.}else{constint index = parentD->children.indexOf(q);//获取在父对象children列表中的indexif(index <0){// we're probably recursing into setParent() from a ChildRemoved event, don't do anything}elseif(parentD->isDeletingChildren){
parentD->children[index]=nullptr;}else{
parentD->children.removeAt(index);//从父对象children列表中移除自己if(sendChildEvents && parentD->receiveChildEvents){
QChildEvent e(QEvent::ChildRemoved, q);QCoreApplication::sendEvent(parent,&e);//如果允许发出子对象移除事件,在下一个事件循环中发出}//子对象移除事件,可以重载[virtual protected] void QObject::childEvent(QChildEvent *event),}//在子对象移除时做相应的处理}}
parent = o;if(parent){// object hierarchies are constrained to a single threadif(threadData != parent->d_func()->threadData){qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");
parent =nullptr;//threadData为数据类QObjectPrivate的成员变量,QAtomicPointer<QThreadData> threadData;return;//在QObject构造函数中赋值,唯一标志一个线程对象,parent->d_func()->threadData代表了新设置的parent}//所处的线程,在Qt中,父子对象必须处在同一个线程中。
parent->d_func()->children.append(q);//将该对象加入到新parent的children列表中if(sendChildEvents && parent->d_func()->receiveChildEvents){if(!isWidget){
QChildEvent e(QEvent::ChildAdded, q);QCoreApplication::sendEvent(parent,&e);//如果允许发出子对象添加事件,发出,同时会发出子对象添加信号}}}}
二、线程亲和性(Thread Affinity)
在QObject的构造函数中,在上面QObject的构造函数中,有如下代码:
auto threadData =(parent &&!parent->thread())? parent->d_func()->threadData.loadRelaxed():QThreadData::current();
threadData->ref();
d->threadData.storeRelaxed(threadData);
这里写自定义目录标题QObject核心特性源码解析欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入QObject核心特性源码解析 #include <iostream> st