Qt - 类的成员变量

在查看qt的源码时候,发现Qt会将数据单独抽象成一个Class##Private 类,所有的成员变量的都是由这个类来保存的。

例如:QThread 类,可以看到从表面上没有看到任何成员变量,那我们就来看看qt是如何巧妙的来完成这个内容的。

class Q_CORE_EXPORT QThread : public QObject
{
    Q_OBJECT
public:
    static Qt::HANDLE currentThreadId() Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
    static QThread *currentThread();

    explicit QThread(QObject *parent = nullptr);
    ~QThread();

....

protected:
    virtual void run();
    int exec();

private:
    Q_DECLARE_PRIVATE(QThread)


    friend class QCoreApplication;
    friend class QThreadData;
};

qt 类的成员变量

Q_DECLARE_PRIVATE(QThread) 

template <typename T> inline T *qGetPtrHelper(T *ptr) { return ptr; }
template <typename Ptr> inline auto qGetPtrHelper(const Ptr &ptr) -> decltype(ptr.operator->()) { return ptr.operator->(); }

// The body must be a statement:
#define Q_CAST_IGNORE_ALIGN(body) QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wcast-align") body QT_WARNING_POP

// 宏

#define Q_DECLARE_PRIVATE(Class) \
    inline Class##Private* d_func() \
    { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
    inline const Class##Private* d_func() const \
    { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
    friend class Class##Private;

2个内联函数,返回时Class##Private* 的指针。

inline Class##Private* d_func()

inline const Class##Private* d_func() const

 

为了让Class##Private 可以访问私有函数,设置为友元类。

friend class Class##Private;

Pirvate的类保存在哪?

qGetPtrHelper的作用是通过模板方式将指针或者对象,转换成指针。

其中d_ptr 是QObject的成员变量的指针,是在类构造函数赋值的,也就Class##Private 类。所以我们也就知道在创建QThread类的时候,QThread会创建一个包含数据成员的类QThreadPrivate

QObject::QObject(QObjectPrivate &dd, QObject *parent)
    : d_ptr(&dd)
{
    Q_D(QObject);
    d_ptr->q_ptr = this;
}

QThread::QThread(QObject *parent)
    : QObject(*(new QThreadPrivate), parent)
{
    Q_D(QThread);
    d->data->thread = this;
}

 

如何访问和使用

Class 访问 ClassPrivate

通过第一节的讲解之后,我们知道了,类是通过Class##Private 类对象保存到d_ptr中的,那如何访问和使用呢,就会用到下面的宏。也就是d_func() 返回一个Class##Private * 类型的指针。

#define Q_D(Class) Class##Private * const d = d_func()

所以访问成员变量就可以直接使用d->data->thread 的方式直接访问。

QThread::QThread(QObject *parent)
    : QObject(*(new QThreadPrivate), parent)
{
    Q_D(QThread);
    d->data->thread = this;
}

 

ClassPrivate 访问  Class

接下来我看一下,在QThreadPrivate中是如何访问QThread的

首先:ClassPrivate都是继承与QObjectPrivate的

第二:和Q_DECLARE_PRIVATE 相对的有Q_DECLARE_PUBLIC的宏就为了访问Class 。形式一样不做过多的介绍。

#define Q_DECLARE_PUBLIC(Class)                                    \
    inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
    inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
    friend class Class;


class QThreadPrivate : public QObjectPrivate
{
public:
    QThreadPrivate(QThreadData *d = 0);
    ~QThreadPrivate();

    mutable QMutex mutex;
    QThreadData *data;
    bool running = false;

    static void setCurrentThread(QThread*) {}
    static QThread *threadForId(int) { return QThread::currentThread(); }
    static QAbstractEventDispatcher *createEventDispatcher(QThreadData *data);

    void ref() {}
    void deref() {}

    Q_DECLARE_PUBLIC(QThread)
};

小结

1、为什么会这样做

由于QThread类是Q_CORE_EXPORT ,是导出类,外部可以可以看到类的声明包括内部变量,但是内部的数据是不希望被外部看到的,所以将所有的数据成员变量封装成一个私有类,不暴露实现细节的目的。

2、通过宏Q_DECLARE_PRIVATE 来声明,Q_D来访问。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值