QT6 源(11):基础类 QObject 与 QMetaObject 的源代码以及成员函数的整理对比,只包括了目前学习到的部分。补充记录 QObject 的完整精简版源码

(1)类 QObject 的简化源代码定义,删除了还没学到的

class Q_CORE_EXPORT QObject
{
public: //Q_OBJECT 直接展开此宏定义得到此函数
    static  const QMetaObject staticMetaObject; 
    virtual const QMetaObject * metaObject() const; 

    Q_PROPERTY(QString objectName  //定义了 objectName 属性 
    		READ objectName 
    		WRITE setObjectName 
    		NOTIFY objectNameChanged
            BINDABLE bindableObjectName)

    QString objectName() const; //返回的是类生成的对象名
    //const char * QMetaObject::className() const; 返回的是类名
    void setObjectName(const QString &name);

    Q_INVOKABLE explicit QObject(QObject * parent = nullptr);
    virtual ~QObject();

    template<typename T> //查找容器中孩子
    inline T findChild(const QString & aName = QString(),  //定义略
    	Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { }

    template<typename T>
    inline QList<T> findChildren(const QString &aName = QString(), 
    	Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
    {  QList<T> list;  return list;   }

#if QT_CONFIG(regularexpression)
    template<typename T>  // 
    inline QList<T> findChildren(const QRegularExpression & re, 
    	Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
    { QList<T> list; return list;    }
#endif // QT_CONFIG(regularexpression)
	
	//typedef QList<QObject *> QObjectList;
    inline const QObjectList & children() const { return d_ptr->children; }

    void setParent(QObject * parent); //此函数定义在这里,加入容器

    static QMetaObject::Connection connect(
    	const QObject * sender  , const char * signal,
        const QObject * receiver, const char * member, 
        Qt::ConnectionType = Qt::AutoConnection);

    static QMetaObject::Connection connect( //这俩是类的静态成员函数
    	const QObject * sender  , const QMetaMethod & signal,
        const QObject * receiver, const QMetaMethod & method,
        Qt::ConnectionType type = Qt::AutoConnection);

    inline QMetaObject::Connection connect( //基于对象的动态成员函数
    	const QObject * sender, const char * signal,
        					 const char    * member, 
        Qt::ConnectionType type = Qt::AutoConnection) const;

    static bool disconnect( //解除信号与槽的静态成员函数
    	const QObject * sender  , const char * signal,
        const QObject * receiver, const char * member);
    static bool disconnect(
    	const QObject * sender  , const QMetaMethod &signal,
        const QObject * receiver, const QMetaMethod &member);
        
    inline bool disconnect( //动态函数默认由信号发送者调用
    							  const char * signal = nullptr,
        const QObject *receiver = nullptr, 
        const char * member = nullptr) const
    { return disconnect(this, signal, receiver, member); }
    
    inline bool disconnect(
    	const QObject * receiver, 
    	const char * member = nullptr) const
    { return disconnect(this, nullptr, receiver, member); }
    
    static bool disconnect(const QMetaObject::Connection &);

    void dumpObjectTree() const;
    void dumpObjectInfo() const;

#ifndef QT_NO_PROPERTIES  //这里出现了动态属性设置
    bool setProperty (const char * name, const QVariant &value);
    QVariant property(const char * name) const; //根据属性名获取属性值,形参是字符串
    //作为对比 QMetaProperty QMetaObject::property(int index) const;
    //根据属性索引返回值属性对象 QMetaProperty对象,形参是数字索引
    QList<QByteArray> dynamicPropertyNames() const;
    QBindingStorage *bindingStorage() { return &d_ptr->bindingStorage; }
    const QBindingStorage *bindingStorage() const { return &d_ptr->bindingStorage; }
#endif // QT_NO_PROPERTIES

Q_SIGNALS:
    void destroyed(QObject * = nullptr); //信号函数不需要实现
    void objectNameChanged(const QString &objectName, QPrivateSignal);

public: //显示本对象所在的容器,或者说返回容器父类
    inline QObject * parent() const { return d_ptr->parent; }
	//而  QMetaObject :: superClass() 则返回继承父类 

	//用于判断本对象是否是形参类及其子类的实现 
    inline bool inherits(const char * classname) const
    {  return const_cast<QObject *>(this)->qt_metacast(classname) != nullptr;  }
	//bool QMetaObject :: inherits(const QMetaObject * metaObject) 用于判断类的继承关系

public Q_SLOTS:
    void deleteLater();

protected:
    QObject * sender() const; //判断信号的发送者
    int senderSignalIndex() const;
    int receivers(const char *signal) const;
    bool isSignalConnected(const QMetaMethod &signal) const;

protected:
    QObject(QObjectPrivate &dd, QObject *parent = nullptr);

protected: //定义了本类的数据成员
    QScopedPointer<QObjectData> d_ptr;

    friend struct QMetaObject; //定义本类的友元类,不止一个,略

private:
    Q_DISABLE_COPY(QObject) //禁止对本类的复制操作
    Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
};

(2)类 QMetaObject 的源码简化版,删除了没学到的,与用不上的,重在快速查找到常用的成员函数并确认其功能

struct Q_CORE_EXPORT QMetaObject
{
    class Connection;
    //QString QObject::objectName() const; 返回值不一样
    const char * className() const;
    const QMetaObject * superClass() const; //返回继承父类
    //而 QObject :: parent() 则返回容器父类,用于内存管理

    bool inherits(const QMetaObject *metaObject) const noexcept;
	//判断本类是否继承于形参类。
	//而 QObject::inherits(const char *)用于判断本对象是否是形参类及其子类的实现

    QObject * cast(QObject *obj) const //用于类型转换,类似于 C++的 dynamic_cast
    { return const_cast<QObject *>(cast(const_cast<const QObject *>(obj))); }
    
    const QObject *cast(const QObject * obj) const; //常量版本
    //功能一样的更好版本是全局模板函数 T * qobject_cast<T *>(A * ptrA)

    QMetaType metaType() const; //获取类型的元类型信息

    //bool QObject::setProperty (const char * name, const QVariant & value);作为对比
    //QVariant QObject::property(const char * name) const; //根据属性名获取属性值,形参是字符串
    int propertyOffset () const;//返回此类的属性偏移量;即此类的第一个属性的索引位置。
    //偏移量是该类的所有基类中所有属性的总和(由于Q0bject具有name()属性,因此总是正数)
    int propertyCount  () const;//返回该类中属性的数量,包括每个基类提供的属性的数量。
    int indexOfProperty(const char * name) const;//返回具有此名的属性的索引,找不到返-1
    //indexOfProperty 的索引基址是 0,搜索范围包括当前类及其所有基类的属性。
    QMetaProperty property(int index) const;//返回具有此索引的属性 QMetaProperty对象
    
    int classInfoOffset() const;//返回此类的第一个类信息项的偏移量,即索引位置。
    //如果类中没有具有类信息的基类,则偏移量为 0;否则,偏移量为类中所有基类中类信息项的总和。
    int classInfoCount () const;//返回的是当前类及其所有基类的类信息总数。
    int indexOfClassInfo(const char *name) const;//找不到则返-1
    //根据类信息名称返回其在元对象中的类信息索引
    //indexOfClassInfo 的索引基址是 0,搜索范围包括当前类及其所有基类的类信息。
    QMetaClassInfo classInfo(int index) const; //根据索引返回类信息

    // internal index-based connect 内部的基于索引的信号连接,形参有很大区别 
    static Connection connect(const QObject *sender, int signal_index,
                        const QObject *receiver, int method_index,
                        int type = 0, int *types = nullptr);
    // internal index-based disconnect  j
    static bool disconnect(const QObject *sender, int signal_index,
                           const QObject *receiver, int method_index);
                              
    // internal slot-name based connect
    static void connectSlotsByName(QObject *o);
    // 使用形式,在窗体的构造函数里这样用 QMetaObject::connectSlotsByName(Widget);

    // internal index-based signal activation 内部用的函数
    static void activate(QObject *sender, int signal_index, void **argv);
    static void activate(QObject *sender, const QMetaObject *, 
    								int local_signal_index, void **argv);

	//似乎是为了处理函数调用的问题。
	//毕竟类的静态函数、动态函数,全局函数、对象函数的调用方式是不一样的
	//本函数有好几个重载形式,全部删除
    static bool invokeMethod(QObject *obj, const char *member,
                             Qt::ConnectionType,
                             QGenericReturnArgument ret,
                             QGenericArgument val0 = QGenericArgument(nullptr),
                             QGenericArgument val1 = QGenericArgument(),
                             QGenericArgument val2 = QGenericArgument(),
                             QGenericArgument val3 = QGenericArgument(),
                             QGenericArgument val4 = QGenericArgument(),
                             QGenericArgument val5 = QGenericArgument(),
                             QGenericArgument val6 = QGenericArgument(),
                             QGenericArgument val7 = QGenericArgument(),
                             QGenericArgument val8 = QGenericArgument(),
                             QGenericArgument val9 = QGenericArgument());

	// 本函数似乎是要创建一个对象,QObect 类型或其子类
    QObject * newInstance(QGenericArgument val0 = QGenericArgument(nullptr),
                         QGenericArgument val1 = QGenericArgument(),
                         QGenericArgument val2 = QGenericArgument(),
                         QGenericArgument val3 = QGenericArgument(),
                         QGenericArgument val4 = QGenericArgument(),
                         QGenericArgument val5 = QGenericArgument(),
                         QGenericArgument val6 = QGenericArgument(),
                         QGenericArgument val7 = QGenericArgument(),
                         QGenericArgument val8 = QGenericArgument(),
                         QGenericArgument val9 = QGenericArgument()) const;

    enum Call {  //定义了这么一个枚举类,似乎是定义函数的功能与类型
        InvokeMetaMethod,
        ReadProperty,
        WriteProperty,
        ResetProperty,
        CreateInstance,
        IndexOfMethod,
        RegisterPropertyMetaType,
        RegisterMethodArgumentMetaType,
        BindableProperty
    };

    template <const QMetaObject & MO>  //模板成员函数
    static constexpr const QMetaObject * staticMetaObject() { return & MO; }

    struct Data { // private data
        SuperData superdata;
        const uint *stringdata;
        const uint *data;
        
        typedef void (*StaticMetacallFunction)
        		(QObject *, QMetaObject::Call, int, void **);
        		
        StaticMetacallFunction static_metacall;
        const SuperData *relatedMetaObjects;
        const QtPrivate::QMetaTypeInterface * const * metaTypes;
        void *extradata; //reserved for future use
    } d;  //本类的数据成员

};

(3)补充记录 QObject 的完整精简版源码

#ifndef QOBJECT_H
#define QOBJECT_H

#ifndef QT_NO_QOBJECT

#include <QtCore/qobjectdefs.h>
#include <QtCore/qstring.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
#ifdef QT_INCLUDE_COMPAT
#include <QtCore/qcoreevent.h>
#endif
#include <QtCore/qscopedpointer.h>
#include <QtCore/qmetatype.h>

#include <QtCore/qobject_impl.h>
#include <QtCore/qbindingstorage.h>

#if __has_include(<chrono>)
#  include <chrono>
#endif

QT_BEGIN_NAMESPACE


template <typename T> class QBindable;
class QEvent;
class QTimerEvent;
class QChildEvent;
struct QMetaObject;
class QVariant;
class QObjectPrivate;
class QObject;
class QThread;
class QWidget;
class QAccessibleWidget;
#if QT_CONFIG(regularexpression)
class QRegularExpression;
#endif
struct QDynamicMetaObjectData;

typedef QList<QObject*> QObjectList;

Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name,
                                           const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options);
Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re,
                                           const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options);
Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options);

class Q_CORE_EXPORT QObjectData
{
    Q_DISABLE_COPY(QObjectData)                                  //该宏表示禁止定义 copy 构造与 copy 赋值运算符函数
public:
    QObjectData() = default;
    virtual ~QObjectData() = 0;
    QObject * q_ptr ; //该成员指出本类描述的是哪个 QObject 对象,回指向 QObject
    QObject * parent; //记录本 QObject 类的所属容器。该功能又继承给 QObject 的所有子类
    QObjectList children; //记录本 QObject 容器包含的所有 QObject 类对象
    //typedef  QList< QObject * >   QObjectList; 类型定义
    //基于此,为了处理 QT中的类对象析构,似宜将所有的类都继承 QObject并将之加入到某个容器中。

    uint isWidget : 1; //以下是记录 QObject 对象应具备的其它属性,看不懂,略
    uint blockSig : 1;
    uint wasDeleted : 1;
    uint isDeletingChildren : 1;
    uint sendChildEvents : 1;
    uint receiveChildEvents : 1;
    uint isWindow : 1; // for QWindow
    uint deleteLaterCalled : 1;
    uint unused : 24;
    int postedEvents;
    QDynamicMetaObjectData *metaObject;
    QBindingStorage bindingStorage;
    QMetaObject *dynamicMetaObject() const;

    enum { CheckForParentChildLoopsWarnDepth = 4096 };

};

class Q_CORE_EXPORT QObject
{
    Q_OBJECT

    Q_PROPERTY(QString            objectName  //定义了 objectName 属性
                READ              objectName
                WRITE          setObjectName
                NOTIFY            objectNameChanged
                BINDABLE  bindableObjectName)
    Q_DECLARE_PRIVATE(QObject)     // 声明私有类


private:
    Q_DISABLE_COPY(QObject) //禁止对本类的复制操作
    Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))

    static QMetaObject::Connection connectImpl(
        const QObject * sender  , void ** signal,
        const QObject * receiver, void ** slotPtr,
        QtPrivate::QSlotObjectBase * slot, Qt::ConnectionType type,
        const int *types, const QMetaObject *senderMetaObject);

    static bool disconnectImpl(const QObject * sender  , void ** signal,
                               const QObject * receiver, void ** slot  ,
                               const QMetaObject * senderMetaObject);

protected:
    virtual void    connectNotify(const QMetaMethod & signal);
    virtual void disconnectNotify(const QMetaMethod & signal);
    bool    isSignalConnected    (const QMetaMethod & signal) const;
    int                 receivers(const char        * signal) const;

    friend struct QMetaObject; //友元类很多,略

    QObject *    sender() const; //判断信号的发送者
    int          senderSignalIndex() const;

    QScopedPointer<QObjectData> d_ptr; //此保护权限的数据成员可被子类使用。
    //这里定义了本类的数据成员,被智能指针包裹

    QObject(QObjectPrivate & dd, QObject * parent = nullptr);

public:
    Q_INVOKABLE explicit QObject(QObject *parent = nullptr);

    virtual ~QObject();

    //返回源文本的翻译版本,
    static QString   tr(const char * sourceText,  //从 ascii码字符串返回 QString字符串
                      const char * disambiguation = nullptr, int n = -1)
    {
        return QString::fromUtf8(sourceText);
    }


//   Q_PROPERTY(QString            objectName  //定义了 objectName 属性
//              READ               objectName
//              WRITE           setObjectName
//              NOTIFY             objectNameChanged
//              BINDABLE   bindableObjectName)
    //这俩函数是上面的 objectName 属性的读写函数,
    //名称由程序员自定义,在 setupUi()函数里被频繁调用
    QString                       objectName() const; //返回的是类生成的对象名
    //const char * QMetaObject::className() const; 返回的是类名
    void                       setObjectName(const QString & name);
    QBindable<QString>    bindableObjectName(); //无官方注释
Q_SIGNALS:  //信号函数不需要实现
    void                          objectNameChanged(const   QString        & objectName,
                                                            QPrivateSignal    );
    //这是属性的信号函数

    //此信号在对象obj被销毁之前立即发出,在任何QPointer实例通知之后,并且不能被阻塞。
    //在发出此信号后,所有对象的子对象将立即被销毁。
    void destroyed(QObject * obj = nullptr);

public Q_SLOTS:
    void deleteLater(); //Note: This function is thread-safe.
    /*
    计划删除此对象。当控制返回事件循环时,该对象将被删除。如果在调用此函数时事件循环并未运行,
    (例如,在调用deleteLater()`之前对象尚未通过`QCoreApplication:exec()'启动),
    那么在启动事件循环后该对象才会被删除。
    如果在主事件循环已停止后调用`deleteLater(),则该对象将不会被删除。
    自Qt 4.8版本起,
    如果在没有运行事件循环的线程中调用`deleteLater()、,该对象将在该线程执行完毕时被销毁。

    请注意,进入和离开一个新的事件循环(例如通过打开一个模态对话框)将不会执行延迟删除;
    要删除该对象,该控件必须从调用deleteLater()的事件循环中返回到事件循环。
    这并不适用于在先前嵌套的事件循环仍在运行时就被删除的对象.
    一旦新的嵌套事件循环启动,Qt事件循环将立即删除这些对象。

    注:安全起见,可以多次调用此函数;
    当第一个延迟删除事件被发送时,该对象的所有待处理事件都会被从事件队列中移除。
    */

public:

#ifndef QT_NO_PROPERTIES  //这里出现了动态属性设置
    //根据属性名获取属性值,形参是字符串
    QVariant                 property(const char * name) const;
    bool                  setProperty(const char * name, const QVariant & value);
    QList<QByteArray> dynamicPropertyNames() const;
    //作为对比 QMetaProperty QMetaObject::property(int index) const;
    //根据属性索引返回值属性对象 QMetaProperty对象,形参是数字索引

    QBindingStorage * bindingStorage()
    { return &d_ptr->bindingStorage; }

    const
    QBindingStorage * bindingStorage() const
    { return &d_ptr->bindingStorage; }
#endif // QT_NO_PROPERTIES

    void dumpObjectTree() const;
    void dumpObjectInfo() const;

    inline bool isWidgetType() const { return d_ptr->isWidget; }

    inline bool isWindowType() const { return d_ptr->isWindow; }

    inline
    bool      signalsBlocked     () const noexcept { return d_ptr->blockSig; }
    bool             blockSignals(bool b) noexcept;

    QThread *        thread() const;
    void       moveToThread(QThread * thread);

    // CoarseTimer 粗调定时器
    int  startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);

    Q_ALWAYS_INLINE  //这是 c++ STL 库里的 chrono 命名空间
    int  startTimer(std::chrono::milliseconds time,
                    Qt::TimerType timerType = Qt::CoarseTimer)
    {   return startTimer(int(time.count()), timerType);   }

    void killTimer(int id);


    //用于判断本对象是否是形参类及其子类的实现
    inline
    bool             inherits(const char * classname) const
    {  return const_cast<QObject *>(this)->qt_metacast(classname) != nullptr;  }
    //bool QMetaObject :: inherits(const QMetaObject * metaObject) 用于判断类的继承关系

    //显示本对象所在的容器,或者说返回容器父类
    inline
    QObject  *        parent() const { return d_ptr->parent; }
    //而  QMetaObject :: superClass() 则返回继承父类
    void           setParent(QObject * parent); //此函数定义在这里,加入容器

    //Returns a list of child objects.
    //typedef QList<QObject *> QObjectList;
    inline const
    QObjectList &     children() const  { return d_ptr->children; }

    //举例: QPushButton *button = pWidget->findChild<QPushButton *>("button1");
    template<typename T> //默认按照递归查找容器中的孩子。模板参数 T应是对象指针类型
    inline
    T             findChild(const QString & aName = QString(),  //按名字查找
        Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
    {
        typedef typename std::remove_cv<
                        typename std::remove_pointer<T>::type
                                          >::type ObjType;

        return static_cast<T>(
    qt_qFindChild_helper(this, aName, ObjType::staticMetaObject, options)
                                    );
    }

    //举例: QList<QWidget *> widgets = p.findChildren<QWidget *>("widgetname");
    template<typename T> // 模板参数 T 是指针类型
    inline
    QList<T>      findChildren(const QString & aName = QString(),
        Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
    {
        typedef typename std::remove_cv<
                        typename std::remove_pointer<T>::type
                                            >::type ObjType;
        QList<T> list;
        qt_qFindChildren_helper(this, aName, ObjType::staticMetaObject,
                    reinterpret_cast<QList<void *> *>(&list), options);
        return list;
    }


    template<typename T>
    inline
    QList<T>      findChildren(const QRegularExpression &re,
        Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
    {
        typedef typename std::remove_cv<
            typename std::remove_pointer<T>::type>::type ObjType;
        QList<T> list;
        qt_qFindChildren_helper(this, re, ObjType::staticMetaObject,
                reinterpret_cast<QList<void *> *>(&list), options);

        return list;
    }

    virtual
    bool               event      (                   QEvent * event);
    virtual
    bool               eventFilter(QObject * watched, QEvent * event);

    void        installEventFilter(QObject * filterObj);
    void         removeEventFilter(QObject *       obj);
protected:
    virtual void  timerEvent(QTimerEvent * event);
    virtual void  childEvent(QChildEvent * event);
    virtual void customEvent(QEvent      * event);

public: //以下全是冗长的信号的连接与断开成员函数,带定义,所以长。

    static QMetaObject::Connection connect(
        const QObject * sender  , const char * signal,
        const QObject * receiver, const char * member,
        Qt::ConnectionType = Qt::AutoConnection);

    static QMetaObject::Connection connect( //这俩是类的静态成员函数
        const QObject * sender  , const QMetaMethod & signal,
        const QObject * receiver, const QMetaMethod & method,
        Qt::ConnectionType type = Qt::AutoConnection);

    inline QMetaObject::Connection connect( //基于对象的动态成员函数
        const QObject * sender, const char * signal,
        const char    * member,
        Qt::ConnectionType type = Qt::AutoConnection) const;

#ifdef Q_CLANG_QDOC
    template<typename PointerToMemberFunction>
    static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection);
    template<typename PointerToMemberFunction, typename Functor>
    static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor);
    template<typename PointerToMemberFunction, typename Functor>
    static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection);
#else
    //Connect a signal to a pointer to qobject member function
    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 *receiver,
                                                                Func2 slot,
                    Qt::ConnectionType type = Qt::AutoConnection)
    {
        typedef QtPrivate::FunctionPointer<Func1> SignalType;
        typedef QtPrivate::FunctionPointer<Func2> SlotType;

        static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
                          "No Q_OBJECT in the class with the signal");

        //compilation error if the arguments does not match.
        static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
                          "The slot requires more arguments than the signal provides.");
        static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
                          "Signal and slot arguments are not compatible.");
        static_assert((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
                          "Return type of the slot is not compatible with the return type of the signal.");

        const int *types = nullptr;
        if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
            types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();

        return connectImpl(sender, reinterpret_cast<void **>(&signal),
                           receiver, reinterpret_cast<void **>(&slot),
                           new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
                                           typename SignalType::ReturnType>(slot),
                            type, types, &SignalType::Object::staticMetaObject);
    }

    //connect to a function pointer  (not a member)
    template <typename Func1, typename Func2>
    static inline
    typename std::enable_if<
            int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0,
                        QMetaObject::Connection
                              >::type //这是函数的返回值
    connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
                Func1 signal, Func2 slot)
    {
        return connect(sender, signal, sender, slot, Qt::DirectConnection);
    }

    //connect to a function pointer  (not a member)
    template <typename Func1, typename Func2>
    static inline
    typename std::enable_if< //这里的 if 的判断条件是个 && 运算
        int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0 &&
        !QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction,
            QMetaObject::Connection //这一行决定了本函的返回值
            >::type
    connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
                Func1 signal,
                const QObject *context, Func2 slot,
                Qt::ConnectionType type = Qt::AutoConnection)
    {
        typedef QtPrivate::FunctionPointer<Func1> SignalType;
        typedef QtPrivate::FunctionPointer<Func2> SlotType;

        static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
                          "No Q_OBJECT in the class with the signal");

        //compilation error if the arguments does not match.
        static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
                          "The slot requires more arguments than the signal provides.");
        static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
                          "Signal and slot arguments are not compatible.");
        static_assert((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
                          "Return type of the slot is not compatible with the return type of the signal.");

        const int *types = nullptr;
        if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
            types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();

        return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
                           new QtPrivate::QStaticSlotObject<Func2,
                                                 typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
                                                 typename SignalType::ReturnType>(slot),
                           type, types, &SignalType::Object::staticMetaObject);
    }

    //connect to a functor
    template <typename Func1, typename Func2>
    static inline
    typename std::enable_if<
        QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1,
            QMetaObject::Connection
                                >::type
    connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
                Func1 signal, Func2 slot)
    {
        return connect(sender, signal,
                       sender, std::move(slot), Qt::DirectConnection);
    }

    //connect to a functor,
    //with a "context" object defining in which
    //event loop is going to be executed
    template <typename Func1, typename Func2>
    static inline
    typename std::enable_if<
        QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1,
            QMetaObject::Connection
                               >::type
    connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
                Func1 signal, const QObject *context, Func2 slot,
                    Qt::ConnectionType type = Qt::AutoConnection)
    {
        typedef QtPrivate::FunctionPointer<Func1> SignalType;
        const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Func2 , typename SignalType::Arguments>::Value;

        static_assert((FunctorArgumentCount >= 0),
                          "Signal and slot arguments are not compatible.");
        const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
        typedef typename QtPrivate::FunctorReturnType<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value>::Value SlotReturnType;

        static_assert((QtPrivate::AreArgumentsCompatible<SlotReturnType, typename SignalType::ReturnType>::value),
                          "Return type of the slot is not compatible with the return type of the signal.");

        static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
                          "No Q_OBJECT in the class with the signal");

        const int *types = nullptr;
        if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
            types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();

        return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
                           new QtPrivate::QFunctorSlotObject<Func2, SlotArgumentCount,
                                typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value,
                                typename SignalType::ReturnType>(std::move(slot)),
                           type, types, &SignalType::Object::staticMetaObject);
    }
#endif //Q_CLANG_QDOC

    static bool disconnect( //解除信号与槽的静态成员函数
        const QObject * sender  , const char * signal,
        const QObject * receiver, const char * member);

    static bool disconnect(
        const QObject * sender  , const QMetaMethod & signal,
        const QObject * receiver, const QMetaMethod & member);

    inline bool disconnect( //动态函数默认由信号发送者调用
        const char    * signal   = nullptr,
        const QObject * receiver = nullptr,
        const char    * member   = nullptr) const
    { return disconnect(this, signal, receiver, member); }

    inline bool disconnect(
        const QObject * receiver,
        const char    * member = nullptr) const
    { return disconnect(this, nullptr, receiver, member); }

    static bool disconnect(const QMetaObject::Connection &);

#ifdef Q_CLANG_QDOC
    template<typename PointerToMemberFunction>
    static bool disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method);
#else
    template <typename Func1, typename Func2>
    static inline bool disconnect(
        const typename QtPrivate::FunctionPointer<Func1>::Object * sender,
                                                            Func1  signal,
        const typename QtPrivate::FunctionPointer<Func2>::Object * receiver,
                                                            Func2  slot )
    {
        typedef QtPrivate::FunctionPointer<Func1> SignalType;
        typedef QtPrivate::FunctionPointer<Func2> SlotType;

        static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
                          "No Q_OBJECT in the class with the signal");

        //compilation error if the arguments does not match.
        static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
                          "Signal and slot arguments are not compatible.");

        return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, reinterpret_cast<void **>(&slot),
                              &SignalType::Object::staticMetaObject);
    }

    template <typename Func1>
    static inline bool disconnect(
        const typename QtPrivate::FunctionPointer<Func1>::Object * sender,
        Func1 signal,  const QObject * receiver, void ** zero)
    {
        // This is the overload for when one wish to disconnect a signal from any slot. (slot=nullptr)
        // Since the function template parameter cannot be deduced from '0', we use a
        // dummy void ** parameter that must be equal to 0
        Q_ASSERT(!zero);
        typedef QtPrivate::FunctionPointer<Func1> SignalType;
        return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, zero,
                              &SignalType::Object::staticMetaObject);
    }
#endif //Q_CLANG_QDOC

}; //结束 class QObject 的定义

inline QMetaObject::Connection
QObject::connect(const QObject *asender, const char *asignal,
                const char *amember, Qt::ConnectionType atype) const
{ return connect(asender, asignal, this, amember, atype); }

template <class T>
inline T qobject_cast(QObject *object)
{
    typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
    static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
                    "qobject_cast requires the type to have a Q_OBJECT macro");
    return static_cast<T>(ObjType::staticMetaObject.cast(object));
}

template <class T>
inline T qobject_cast(const QObject *object)
{
    typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
    static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
                      "qobject_cast requires the type to have a Q_OBJECT macro");
    return static_cast<T>(ObjType::staticMetaObject.cast(object));
}


template <class T> inline const char * qobject_interface_iid()
{ return nullptr; }

inline const QBindingStorage *qGetBindingStorage(const QObject *o)
{
    return o->bindingStorage();
}
inline QBindingStorage *qGetBindingStorage(QObject *o)
{
    return o->bindingStorage();
}

#if defined(Q_CLANG_QDOC)
#  define Q_DECLARE_INTERFACE(IFace, IId)
#elif !defined(Q_MOC_RUN)
#  define Q_DECLARE_INTERFACE(IFace, IId) \
    template <> inline const char *qobject_interface_iid<IFace *>() \
    { return IId; } \
    template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
    { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : nullptr)); } \
    template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
    { return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : nullptr)); }
#endif // Q_MOC_RUN

#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
#endif

class QSignalBlocker
{
public:
    inline explicit QSignalBlocker(QObject *o) noexcept;
    inline explicit QSignalBlocker(QObject &o) noexcept;
    inline ~QSignalBlocker();

    inline QSignalBlocker(QSignalBlocker &&other) noexcept;
    inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept;

    inline void reblock() noexcept;
    inline void unblock() noexcept;

private:
    Q_DISABLE_COPY(QSignalBlocker)
    QObject *m_o;
    bool m_blocked;
    bool m_inhibited;
};

QSignalBlocker::QSignalBlocker(QObject *o) noexcept
    : m_o(o),
      m_blocked(o && o->blockSignals(true)),
      m_inhibited(false)
{}

QSignalBlocker::QSignalBlocker(QObject &o) noexcept
    : m_o(&o),
      m_blocked(o.blockSignals(true)),
      m_inhibited(false)
{}

QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) noexcept
    : m_o(other.m_o),
      m_blocked(other.m_blocked),
      m_inhibited(other.m_inhibited)
{
    other.m_o = nullptr;
}

QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) noexcept
{
    if (this != &other) {
        // if both *this and other block the same object's signals:
        // unblock *this iff our dtor would unblock, but other's wouldn't
        if (m_o != other.m_o || (!m_inhibited && other.m_inhibited))
            unblock();
        m_o = other.m_o;
        m_blocked = other.m_blocked;
        m_inhibited = other.m_inhibited;
        // disable other:
        other.m_o = nullptr;
    }
    return *this;
}

QSignalBlocker::~QSignalBlocker()
{
    if (m_o && !m_inhibited)
        m_o->blockSignals(m_blocked);
}

void QSignalBlocker::reblock() noexcept
{
    if (m_o)
        m_o->blockSignals(true);
    m_inhibited = false;
}

void QSignalBlocker::unblock() noexcept
{
    if (m_o)
        m_o->blockSignals(m_blocked);
    m_inhibited = true;
}

namespace QtPrivate {
    inline QObject & deref_for_methodcall(QObject &o) { return  o; }
    inline QObject & deref_for_methodcall(QObject *o) { return *o; }
}
#define Q_SET_OBJECT_NAME(obj) QT_PREPEND_NAMESPACE(QtPrivate)::deref_for_methodcall(obj).setObjectName(QLatin1String(#obj))

QT_END_NAMESPACE

#endif

#endif // QOBJECT_H

(4)

谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangzhangkeji

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值