在QObject中定义了一个保护权限的成员变量 d_ptr
其中 QObjectConnectionListVector *connectionLists 是一个QVector<QObjectPrivate::ConnectionList>
3、int QObjectPrivate:: signalIndex const char *signalName,const QMetaObject **meta) const 返回信号的绝对索引
protected:
QScopedPointer<QObjectData> d_ptr;
QScopePointer<> 是一个模板类,维护特定类型的指针,这里d_ptr 相当于一个QObjectData对象的指针。
QObject 几乎是所有QT中的类的基类,因此QT中每个继承于Qobject的类都有这个指针,指向一个动态分配的QObjectData对象。
QObjectData类的定义
class Q_CORE_EXPORT QObjectData {
public:
virtual ~QObjectData() = 0;
QObject *q_ptr; 对象this指针
QObject *parent; 父对象指针
QObjectList children; typedef QList<QObject*> QObjectList; 这个是对象的子对象链表,区别于父类和子类
uint isWidget : 1; 是否是Wideget类型
uint blockSig : 1; 是否处于信号阻塞
uint wasDeleted : 1; 防止多次delete对象
uint isDeletingChildren : 1; 是否在delete子对象
uint sendChildEvents : 1; 是否向父对象报告对象插入和删除事件 应该为true
uint receiveChildEvents : 1; 是否接收子对象的事件消息 应该为ture
uint isWindow : 1; //for QWindow
uint unused : 25;
int postedEvents;
QDynamicMetaObjectData *metaObject;
QMetaObject *dynamicMetaObject() const;
};
在QObject的构造函数中对d_ptr进行了初始化
QObject::QObject(QObject *parent)
: d_ptr(new QObjectPrivate) 这里是构建了一个QObjectPrivate对象,并将其指针赋给d_ptr
{
....................................省略
}
QObjectPrivate 是QObjectData的子类,这样就合情合理了。 事实上这个类是如此的重要,也是信息量很大的一个结构
class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
Q_DECLARE_PUBLIC(QObject)
public:
struct ExtraData
{
ExtraData() {}
#ifndef QT_NO_USERDATA
QVector<QObjectUserData *> userData;
#endif
QList<QByteArray> propertyNames;
QVector<QVariant> propertyValues;
QVector<int> runningTimers;
QList<QPointer<QObject> > eventFilters;
QString objectName;
}; //一些结构分别用来存放对象所属类的 property 运行时间等信息
typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
struct Connection //重要的结构 保存每个信号和槽的连接
{
QObject *sender; 发送对象的指针
QObject *receiver; 接受对象的指针
union {
StaticMetaCallFunction callFunction; 接受对象的qt_static_metacall函数的指针
QtPrivate::QSlotObjectBase *slotObj;
};
// The next pointer for the singly-linked ConnectionList
Connection *nextConnectionList;
//senders linked list
Connection *next;
Connection **prev;
QAtomicPointer<const int> argumentTypes; 参数值数组指针
QAtomicInt ref_;
ushort method_offset;
ushort method_relative;
uint signal_index : 27; // In signal range (see QObjectPrivate::signalIndex())
ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
ushort isSlotObject : 1;
ushort ownArgumentTypes : 1;
Connection() : nextConnectionList(0), ref_(2), ownArgumentTypes(true) {
//ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
}
~Connection();
int method() const { Q_ASSERT(!isSlotObject); return method_offset + method_relative; }
void ref() { ref_.ref(); }
void deref() {
if (!ref_.deref()) {
Q_ASSERT(!receiver);
delete this;
}
}
};
// ConnectionList is a singly-linked list 信号对应的槽链表,每一个信号对应一个该结构,每一个连接保存在一个connection
struct ConnectionList {
ConnectionList() : first(0), last(0) {}
Connection *first;
Connection *last;
};
struct Sender
{
QObject *sender;
int signal;
int ref;
};
QObjectPrivate(int version = QObjectPrivateVersion);
virtual ~QObjectPrivate();
void deleteChildren();
void setParent_helper(QObject *);
void moveToThread_helper();
void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
void _q_reregisterTimers(void *pointer);
bool isSender(const QObject *receiver, const char *signal) const;
QObjectList receiverList(const char *signal) const;
QObjectList senderList() const;
void addConnection(int signal, Connection *c);
void cleanConnectionLists();
static inline Sender *setCurrentSender(QObject *receiver,
Sender *sender);
static inline void resetCurrentSender(QObject *receiver,
Sender *currentSender,
Sender *previousSender);
static QObjectPrivate *get(QObject *o) {
return o->d_func();
}
int signalIndex(const char *signalName, const QMetaObject **meta = 0) const;
inline bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const;
inline bool isDeclarativeSignalConnected(uint signalIdx) const;
// To allow abitrary objects to call connectNotify()/disconnectNotify() without making
// the API public in QObject. This is used by QQmlNotifierEndpoint.
inline void connectNotify(const QMetaMethod &signal);
inline void disconnectNotify(const QMetaMethod &signal);
template <typename Func1, typename Func2>
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
Qt::ConnectionType type = Qt::AutoConnection);
template <typename Func1, typename Func2>
static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot);
static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index,
const QObject *receiver, void **slot,
QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
const int *types, const QMetaObject *senderMetaObject);
static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type);
static bool disconnect(const QObject *sender, int signal_index, void **slot);
public:
ExtraData *extraData; // extra data set by the user
QThreadData *threadData; // id of the thread that owns the object
QObjectConnectionListVector *connectionLists;
Connection *senders; // linked list of connections connected to this object
Sender *currentSender; // object currently activating the object
mutable quint32 connectedSignals[2];
union {
QObject *currentChildBeingDeleted;
QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
};
// these objects are all used to indicate that a QObject was deleted
// plus QPointer, which keeps a separate list
QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
};
其中 QObjectConnectionListVector *connectionLists 是一个QVector<QObjectPrivate::ConnectionList>
class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList>
{
public:
bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse
bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet
int inUse; //number of functions that are currently accessing this object or its connections
QObjectPrivate::ConnectionList allsignals;
QObjectConnectionListVector()
: QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)
{ }
QObjectPrivate::ConnectionList &operator[](int at)
{
if (at < 0)
return allsignals;
return QVector<QObjectPrivate::ConnectionList>::operator[](at);
}
};
结构图如下
1、QObjectList QObjectPrivate::receiverList(const char *signal) const 返回指定信号关联的接受对象的列表
QObjectList QObjectPrivate::receiverList(const char *signal) const
{
Q_Q(const QObject);
QObjectList returnValue;
int signal_index = signalIndex(signal); 返回绝对索引
if (signal_index < 0)
return returnValue;
QMutexLocker locker(signalSlotLock(q));
if (connectionLists) {
if (signal_index < connectionLists->count()) {
const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first; 根据索引在QVector中找到对应的ConnectionList,first指向表头
while (c) {
if (c->receiver)
returnValue << c->receiver;
c = c->nextConnectionList; 遍历这个单项链表,将receiver不为空的添加到QObjectList
}
}
}
return returnValue;
}
2、QObjectList QObjectPrivate::senderList() const 返回链接到改对象的 对象列表
QObjectList QObjectPrivate::senderList() const
{
QObjectList returnValue;
QMutexLocker locker(signalSlotLock(q_func()));
for (Connection *c = senders; c; c = c->next)
returnValue << c->sender; 通过遍历senders
return returnValue;
}
3、int QObjectPrivate:: signalIndex const char *signalName,const QMetaObject **meta) const 返回信号的绝对索引
int QObjectPrivate::signalIndex(const char *signalName,
const QMetaObject **meta) const
{
Q_Q(const QObject); //宏 q=this
const QMetaObject *base = q->metaObject();
Q_ASSERT(QMetaObjectPrivate::get(base)->revision >= 7);
QArgumentTypeArray types;
QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signalName, types);
int relative_index = QMetaObjectPrivate::indexOfSignalRelative(
&base, name, types.size(), types.constData());
if (relative_index < 0)
return relative_index;
relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
if (meta)
*meta = base;
return relative_index + QMetaObjectPrivate::signalOffset(base); +offset 返回绝对索引 索引相对于全部的信号包括继承来的
}
void QObjectPrivate::addConnection(int signal, Connection *c)
{
Q_ASSERT(c->sender == q_ptr);
if (!connectionLists)
connectionLists = new QObjectConnectionListVector(); 如果容器为空创建它
if (signal >= connectionLists->count())
connectionLists->resize(signal + 1); 根据信号的索引,如果容器对应的索引位置为空,表示还没有为信号连接任何函数,调整容器大小,
在对应的位置构建信号关联的ConnectionList
ConnectionList &connectionList = (*connectionLists)[signal];
if (connectionList.last) {
connectionList.last->nextConnectionList = c;
} else {
connectionList.first = c;
}
connectionList.last = c; //.last始终指向最后加入的connection
cleanConnectionLists();
c->prev = &(QObjectPrivate::get(c->receiver)->senders);
c->next = *c->prev;
*c->prev = c; //加到接收对象的senders的链表里
if (c->next)
c->next->prev = &c->next;
if (signal < 0) {
connectedSignals[0] = connectedSignals[1] = ~0;
} else if (signal < (int)sizeof(connectedSignals) * 8) {
connectedSignals[signal >> 5] |= (1 << (signal & 0x1f));
}
}