Q_DECLARE_PRIVATE和Q_DECLARE_PUBLIC

两个宏的释义?作用?实现?用法?

作用

        Q_DECLARE_PRIVATE是为了实现QT内部的Q指针和D指针功能的宏定义,通过Q/D指针来保证程序的二进制兼容。

什么是二进制兼容?

        简单的来说,就是随着lib/dll库的更新迭代,调用库文件的程序在不需要重编译的情况下仍能够正常使用,以达到"兼容"二进制库文件的变化,这就叫做二进制兼容。对应二进制兼容的还有源代码兼容:就是需要对程序重新编译才能使用新的库文件。

        Q/D指针只是Qt实现二进制兼容的一种方法,简单的来说就是将功能通过指针对象私有化,隐藏起来具体的细节。比如对于一个InfterfaceClass, 它所提供的所有接口都是通过一个InfterfaceClassPrivate objectPoint来具体操作的,InfterfaceClassPrivate代表插件或者库,库无论如何变化都不会影响到objectPoint的指针在内存中存放的顺序和位置。

class InfterfaceClass
{
    public:
        InfterfaceClass();
        ~InfterfaceClass();

        int getNumber() const
        {
            return m_d->getNumber();
        }

        void setNumber(int number)
        {
            m_d->setNumber(number);
        }

    private:
        InfterfaceClassPrivate* m_d;
}

        实现二进制兼容的方法有很多,我们中先重点了解Q/D指针的原理。

Q/D指针的原理

        d指针指向封装的私有类,q指针指向公共的类。通过继承转换,将private指针强转(reinterpret_cast<>)为对应的子类private指针对象。

自定义实现Q/D指针的类:借助PImpl(private implementation, 从代码实现角度上说也可以叫point to implementation,是一种简单的桥接模式)机制

注意:使用Q/D指针宏时需要在.pro中添加core-private

实现和使用Q/D指针

        考虑到多重继承,所以被继承的最root base class(非private class)才会有一个private object pointer,借助于reinterpret_cast强转函数完成类型转换

        为什么要在origion base class中才会拥有private object pointer?而不是在每一个inherit class 中都创建这样一个成员变量?因为多重继承下,在构造函数中会将每一个继承下来private class 都构造一遍

        

//widget.h
class Widget
{
public:
    Widget();

protected:
    Widget(WidgetPrivate& d); //allow subclass access the method
    WidgetPrivate* d_ptr;
}


//widget.cpp
Widget::Widget():d_ptr(new WidgetPrivate(this))
{
}

Widget::Widget(WidgetPrivate& d): d_ptr(&d)
{
}

/*******************  splite line   **************************/

//widget_p.h
struct WidgetPrivate
{
    WidgetPrivate(Widget* q): q_ptr(q){}
    Widget* q_ptr;
    Rect geometry;
    String styleString;
}



/*******************  splite line   **************************/

//label.h
class Label: public Widget
{
Q_DECLARE_PRIVATE(Label)
public:
    Label();
    void setText(const QString& text);

protected:
    Label(LabelPrivate& d);
}

//label.cpp

#include "widget_p.h"
class LabelPrivate: WidgetPrivate
{
public:
    String text;
}


//initialize the d-pointer with our own Private
Label::Label():Widget(*new LabelPrivate)
{
}

Label:Label(LabelPrivate& d): Widget(d)
{
}

//with Q_D you can use the numbers od LabelPrivate form Label
void Label::setText(const QString& text)
{
    Q_D(Label);
    d->text = text;
}

//with Q_Q you can use the numbers of Label from LabelPrivate
void LabelPrivate::someHelpFunction()
{
    Q_Q(Label);
    q->selectAll();
}

另一个参考实现:

//lineedit.h


#ifndef LINEEDIT_H
#define LINEEDIT_H

#include <QLineEdit>

class LineEditPrivate;
class LineEdit:public QLineEdit
{
    Q_OBJECT
public:
    explicit LineEdit(QWidget *parent=nullptr);
    virtual ~LineEdit();
    void setTipText(const QString &text);

signals:
    void verificationResult(bool,QString);

protected:
    LineEdit(LineEditPrivate &d,QWidget *parent=nullptr);
    LineEditPrivate * d_ptr;
private:
    Q_DECLARE_PRIVATE(LineEdit)
};

#endif // LINEEDIT_H

//lineedit.cpp



#include "lineedit.h"
#include "lineedit_p.h"

LineEdit::LineEdit(QWidget *parent):
    QLineEdit(parent),
    d_ptr(new LineEditPrivate(this))
{

}

LineEdit::~LineEdit()
{
    Q_D(LineEdit);

    delete d;
}

void LineEdit::setTipText(const QString &text)
{
    Q_D(LineEdit);
    d->tipText = text;
}


LineEdit::LineEdit(LineEditPrivate &d, QWidget *parent):
    d_ptr(&d),
    QLineEdit(parent)
{

}

lineeditprivate的实现

#ifndef LINEEDIT_P_H
#define LINEEDIT_P_H

#include <QObject>
class LineEdit;
class LineEditPrivate{

    Q_DECLARE_PUBLIC(LineEdit)
public:

    LineEditPrivate(){}
    ~LineEditPrivate(){}

    LineEditPrivate(LineEdit *parent):
        q_ptr(parent){}

    //data
    QString tipText;
    QRegExp regExp;

protected:
    LineEdit * q_ptr;
};

#endif // LINEEDIT_P_H

下面是subclass of LineEdit

#ifndef INTEDIT_H
#define INTEDIT_H

#include "lineedit.h"

class IntEditPrivate;

class IntEdit:public LineEdit
{
    Q_OBJECT
public:
    explicit IntEdit(QWidget *parent=nullptr);
    virtual ~IntEdit();

protected:

private:
    Q_DECLARE_PRIVATE(IntEdit)
};

#endif // INTEDIT_H

#include "intedit.h"

#include "lineedit_p.h"

class IntEditPrivate:public LineEditPrivate{
    Q_DECLARE_PUBLIC(IntEdit)
public:
    IntEditPrivate(){}
    ~IntEditPrivate(){}

    QString test;
};

IntEdit::IntEdit(QWidget *parent):
    LineEdit(*new IntEditPrivate,parent)
{
    Q_D(IntEdit);
    d->test = "AAA";
}

IntEdit::~IntEdit()
{

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值