d/q指针的原理
参考链接
维基百科上讲得很详细,故不再进行赘述。
关于为什么写这篇文章
最近因为自定义输入框,采用了d/p指针来实现二进制兼容。在参考官方例子,也就是上面的参考链接时,始终都无法实现。一直报错无法调用已删除函数。最后实在没有办法去查阅Qt源码,参考了QLineEdit本身的实现,发现了是因为没有给Private加默认构造函数构成的。
为什么类的数据类要以Private结尾?
这是因为Q_D宏定义的
#define Q_D(Class) Class##Private * const d = d_func()
一个具体的例子的描述
- 定义一个类LineEdit,继承于QLineEdit;
- 定义一个子类,继承于LineEdit;
具体代码实现
lineedit_p.h
#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
lineedit.h
#ifndef LINEEDIT_H
#define LINEEDIT_H
#include <QLineEdit>
#include <QFocusEvent>
class QRegExp;
class LineEditPrivate;
class LineEdit:public QLineEdit
{
Q_OBJECT
public:
explicit LineEdit(QWidget *parent=nullptr);
virtual ~LineEdit();
void setRegExp(const QRegExp ®Exp);
void setTipText(const QString &text);
void clearRegExp();
signals:
void verificationResult(bool,QString);
protected:
void updateValidator();
void focusOutEvent(QFocusEvent *pEvent);
LineEdit(LineEditPrivate &d,QWidget *parent=nullptr);
LineEditPrivate * d_ptr;
private:
Q_DECLARE_PRIVATE(LineEdit)
Q_DISABLE_COPY(LineEdit)
};
#endif // LINEEDIT_H
lineedit.cpp
#include "lineedit.h"
#include <QRegExp>
#include <QRegExpValidator>
#include "lineedit_p.h"
LineEdit::LineEdit(QWidget *parent):
QLineEdit(parent),
d_ptr(new LineEditPrivate(this))
{
}
LineEdit::~LineEdit()
{
Q_D(LineEdit);
delete d;
}
void LineEdit::setRegExp(const QRegExp ®Exp)
{
Q_D(LineEdit);
d->regExp = regExp;
}
void LineEdit::setTipText(const QString &text)
{
Q_D(LineEdit);
d->tipText = text;
}
void LineEdit::clearRegExp()
{
Q_D(LineEdit);
d->regExp.setPattern("");
}
void LineEdit::focusOutEvent(QFocusEvent *pEvent)
{
Q_D(LineEdit);
if(!d->regExp.exactMatch(this->text())){
this->setStyleSheet("QLineEdit{border:1px solid red }");
emit verificationResult(false,d->tipText);
}else{
this->setStyleSheet("QLineEdit{border:1px solid gray border-radius:1px}");
emit verificationResult(true,"");
}
QLineEdit::focusOutEvent(pEvent);
}
LineEdit::LineEdit(LineEditPrivate &d, QWidget *parent):
d_ptr(&d),
QLineEdit(parent)
{
}
intedit.h
#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
intedit.cpp
#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()
{
}