學習記錄-Qt中使用Q指標和D指標
阿新 • • 發佈:2018-12-20
總結網上看到的文章,使用D指標的好處如下:
1.保證程式碼的二進位制相容性;
2.隱藏實現細節;
3.提高編譯速度;
Qt關於D指標和Q指標的定義:
d_ptr指標指向私有實現類,使用如下巨集定義輔助函式和宣告友元類
#define Q_DECLARE_PRIVATE(Class) / inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } / inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } / friend class Class##Private;
q_ptr指標指向父類,使用如下巨集定義輔助函式和宣告友元類
#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;
使用D指標和Q指標的巨集定義
#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()
/* Some classes do not permit copies to be made of an object. These classes contains a private copy constructor and assignment operator to disable copying (the compiler gives an error message). */ #define Q_DISABLE_COPY(Class) \ Class(const Class &) Q_DECL_EQ_DELETE;\ Class &operator=(const Class &) Q_DECL_EQ_DELETE;
定義一個類如下:
class TestClassPrivate;
class TestClass
{
public:
TestClass();
~TestClass();
private:
TestClassPrivate * const d_ptr;
Q_DECLARE_PRIVATE(TestClass);
};
定義一個私有類如下:
class TestClass;
class TestClassPrivate
{
public:
TestClassPrivate(TestClass *q);
private:
TestClass * const q_ptr;
Q_DECLARE_PUBLIC(TestClass);
int m_val1;
};
一個例項:
testclass.h
#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <QObject>
class TestClassPrivate;
class TestClass
{
public:
explicit TestClass(QObject *parent);
~TestClass();
void doFunc();
private:
void showMsg(QString str);
private:
TestClassPrivate * const d_ptr;
Q_DECLARE_PRIVATE(TestClass);
Q_DISABLE_COPY(TestClass);
};
#endif // TESTCLASS_H
testclass.cpp
#include "testclass.h"
#include <QtDebug>
class TestClassPrivate
{
public:
TestClassPrivate(TestClass *q) :
q_ptr(q)
{
}
void testFunc()
{
Q_Q(TestClass);
q->showMsg("hello!");
}
private:
TestClass * const q_ptr;
Q_DECLARE_PUBLIC(TestClass);
};
TestClass::TestClass(QObject *parent):
d_ptr(new TestClassPrivate(this))
{
}
TestClass::~TestClass()
{
Q_D(TestClass);
delete d;
}
void TestClass::doFunc()
{
Q_D(TestClass);
d->testFunc();
}
void TestClass::showMsg(QString str)
{
qDebug() << str;
}
以上是使用Qt自帶巨集實現。
存在問題:
1.d_ptr需要手動釋放,有可能粗心忘記了;
2.d_ptr和q_pt的宣告看起來不夠簡潔;
問題改進:
1.使用QScopedPointer,不用關注D指標的釋放;
2.使用巨集改進使用;
#define DQ_DECLARE_PRIVATE(Class) \
Q_DECLARE_PRIVATE(Class) \
QScopedPointer<Class##Private> d_ptr;
#define DQ_DECLARE_PUBLIC(Class) \
Q_DECLARE_PUBLIC(Class) \
Class* q_ptr;
#define DQ_SAFE_DELETE(p) do { if(p) { delete (p); (p) = 0; } } while(0)
使用例項:
dqglobal.h
#ifndef DQGLOBAL_H
#define DQGLOBAL_H
#include <QtGlobal>
#include <QScopedPointer>
#define DQ_DECLARE_PRIVATE(Class) \
Q_DECLARE_PRIVATE(Class) \
QScopedPointer<Class##Private> d_ptr;
#define DQ_DECLARE_PUBLIC(Class) \
Q_DECLARE_PUBLIC(Class) \
Class* q_ptr;
#define DQ_SAFE_DELETE(p) do { if(p) { delete (p); (p) = 0; } } while(0)
#endif // DQGLOBAL_H
testclass.h
#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <QObject>
#include "dqglobal.h"
class TestClassPrivate;
class TestClass
{
DQ_DECLARE_PRIVATE(TestClass)
public:
explicit TestClass(QObject *parent);
~TestClass();
void doFunc();
private:
void showMsg(QString str);
//private:
// TestClassPrivate * const d_ptr;
// Q_DECLARE_PRIVATE(TestClass);
// Q_DISABLE_COPY(TestClass);
};
#endif // TESTCLASS_H
testclass.cpp
#include "testclass.h"
#include <QtDebug>
class TestClassPrivate
{
DQ_DECLARE_PUBLIC(TestClass)
public:
TestClassPrivate(TestClass *q) :
q_ptr(q)
{
}
void testFunc()
{
Q_Q(TestClass);
q->showMsg("hello!");
}
//private:
// TestClass * const q_ptr;
// Q_DECLARE_PUBLIC(TestClass);
};
TestClass::TestClass(QObject *parent):
d_ptr(new TestClassPrivate(this))
{
}
TestClass::~TestClass()
{
// Q_D(TestClass);
// delete d;
}
void TestClass::doFunc()
{
Q_D(TestClass);
d->testFunc();
}
void TestClass::showMsg(QString str)
{
qDebug() << str;
}