再次回到QtCoreApplication类
终于完成了考试,可以恢复正常的生活了,继续我的源码分析之路。不知道会不会进决赛,如果进了,那么又需要一段时间来准备决赛的事情,看来,数据结构是免不了的了,终于要好好去看一次数据结构了。
好了,不说别的了,继续今天的分析。今天,我们又一次来到QtCoreApplication类,看看这个类是怎么调用线程那些东西的。
在QtCoreApplication类的exec()方法:
if (!QCoreApplicationPrivate::checkInstance("exec"))
return -1;
QThreadData *threadData = self->d_func()->threadData;
if (threadData != QThreadData::current()) {
qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
return -1;
}
if (!threadData->eventLoops.isEmpty()) {
qWarning("QCoreApplication::exec: The event loop is already running");
return -1;
}
threadData->quitNow = false;
QEventLoop eventLoop;
self->d_func()->in_exec = true;
self->d_func()->aboutToQuitEmitted = false;
int returnCode = eventLoop.exec();
threadData->quitNow = false;
if (self) {
self->d_func()->in_exec = false;
if (!self->d_func()->aboutToQuitEmitted)
emit self->aboutToQuit();
self->d_func()->aboutToQuitEmitted = true;
sendPostedEvents(0, QEvent::DeferredDelete);
}
return returnCode;
我重点想知道的是,d_func()函数如何得到QThreadData对象的,这个需要进入到QCoreApplicationPrivate类当中了。
发现了这样的定义:
#define Q_DECLARE_PRIVATE(Class) /
inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } /
inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } /
friend class Class##Private;
原来该类调用了qGetPtrHelper方法,继续跟踪下去:
template <typename T> static inline T *qGetPtrHelper(T *ptr) { return ptr; }
template <typename Wrapper> static inline typename Wrapper::pointer qGetPtrHelper(const Wrapper &p) { return p.data(); }
其实d_func()是将QObjectData类的指针转换为QCoreApplicatPrivate类的指针。看下继承关系,QCoreApplicatPrivate继承自QObjectPrivate,QObjectPrivate继承自QObjectData;但是这样的转换还是会带来危险,因为本来这个指针就不是该类的,这样相当于扩大了对象的引用内存的大小,容易产生越界错误。而且这样的强转之后,也只是调用了其中来自 QObjectData的方法,这里的用意不是很明白,应该在其他地方对应用指针做了新的赋值。去找找看。
QScopedPointer<QObjectData> d_ptr的定义来自QObject,现在找找看,是否有对该指针的赋值:
QObject::QObject(QObject *parent): d_ptr(new QObjectPrivate)
实际的引用对象就是QObjectPrivate类的对象了。
现在就可以总结一下了,整个Qt控制台应用程序框架基本明了:
我们编写的代码是:
QCoreApplication a(argc,argv);
a. exec();
通过这两行代码,Qt为我们做了如下工作:
首先创建一个用于保存整个程序运行核心数据的类对象:
QCoreApplication继承自QObject,所以,首先构造QOjbect类对象,于是有了:
D_ptr(new QObjectPrivate)
随后对QThread进行初始化:
#ifndef QT_NO_THREAD
QThread::initialize();
#endif
接下来创建事件派送器,从Windows中将消息传递至Qt,并进行分发,构造函数完成。
随后调用a.exec()方法,获取线程信息:
QThreadData *threadData = self->d_func()->threadData;
最后进入事件循环,并进行事件发送等。
今天就只能分析到这里了,忙了一天,比较累了,要早点休息了。明天继续,详细看下事件循环部分,随后开始对QApplication类进行分析。
2009年11月1日星期日 23:16