Pimpl(Pointer to Implementation)是一种设计模式,用于将类的接口与实现分离,从而隐藏实现细节,降低编译依赖,提高代码的可维护性和可扩展性。这种模式在 Qt 中被称为 D-Pointer,广泛应用于 Qt 框架中。
在 Qt 中,D-Pointer 的实现主要通过以下宏来完成:
Q_DECLARE_PRIVATE
:在公共类中声明一个指向私有实现类的指针。Q_DECLARE_PUBLIC
:在私有实现类中声明一个指向公共类的指针。Q_D
和 Q_Q
:在公共类和私有实现类中分别用于访问对方。ElaApplication
#include
#include "ElaApplicationPrivate.h" // 包含私有实现类的声明
class ElaApplication : public QObject {
Q_OBJECT
Q_DECLARE_PRIVATE(ElaApplication) // 声明私有实现类指针
public:
explicit ElaApplication(QObject *parent = nullptr);
~ElaApplication();
void setIsEnableMica(bool enable);
bool isEnableMica() const;
void setMicaImagePath(const QString &path);
QString micaImagePath() const;
private:
ElaApplicationPrivate *d_ptr; // 指向私有实现类的指针
};
ElaApplicationPrivate
#include "ElaApplication.h"
class ElaApplicationPrivate {
Q_DECLARE_PUBLIC(ElaApplication) // 声明公共类指针
public:
ElaApplicationPrivate(ElaApplication *q);
~ElaApplicationPrivate();
bool isEnableMica;
QString micaImagePath;
private:
ElaApplication *q_ptr; // 指向公共类的指针
};
ElaApplication.cpp
#include "ElaApplication.h"
#include "ElaApplicationPrivate.h"
ElaApplication::ElaApplication(QObject *parent)
: QObject(parent), d_ptr(new ElaApplicationPrivate(this)) {
Q_D(ElaApplication); // 使用 Q_D 宏获取私有实现指针
d->isEnableMica = false; // 初始化私有成员
}
ElaApplication::~ElaApplication() {
delete d_ptr; // 删除私有实现
}
void ElaApplication::setIsEnableMica(bool enable) {
Q_D(ElaApplication); // 使用 Q_D 宏获取私有实现指针
d->isEnableMica = enable;
}
bool ElaApplication::isEnableMica() const {
Q_D(const ElaApplication); // 使用 Q_D 宏获取私有实现指针
return d->isEnableMica;
}
void ElaApplication::setMicaImagePath(const QString &path) {
Q_D(ElaApplication); // 使用 Q_D 宏获取私有实现指针
d->micaImagePath = path;
}
QString ElaApplication::micaImagePath() const {
Q_D(const ElaApplication); // 使用 Q_D 宏获取私有实现指针
return d->micaImagePath;
}
Q_DECLARE_PRIVATE
、Q_DECLARE_PUBLIC
和 Q_D
等宏,Qt 提供了一种简洁的方式来实现 Pimpl 模式。希望这些信息能帮助你更好地理解 Qt 的 D-Pointer(Pimpl)设计模式!
Car
的头文件#include
class CarPrivate; // 前置声明私有类
class Car : public QObject {
Q_OBJECT
// Q_DECLARE_PRIVATE 宏展开
// 原始宏定义:
// #define Q_DECLARE_PRIVATE(Class) \
// inline Class##Private* d_func() { return reinterpret_cast(qGetPtrHelper(d_ptr)); } \
// inline const Class##Private* d_func() const { return reinterpret_cast(qGetPtrHelper(d_ptr)); } \
// friend class Class##Private;
inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取非const的私有实现
inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取const的私有实现
friend class CarPrivate; // 声明私有实现类为友元类
public:
Car(QObject *parent = nullptr);
~Car();
void startEngine(); // 公共方法
private:
CarPrivate *d_ptr; // 指向私有实现类的指针
};
CarPrivate
的头文件#include "Car.h"
class CarPrivate {
// Q_DECLARE_PUBLIC 宏展开
// 原始宏定义:
// #define Q_DECLARE_PUBLIC(Class) \
// Class *q_ptr; \
// inline Class *q_func() { return q_ptr; } \
// inline const Class *q_func() const { return q_ptr; }
Car *q_ptr; // 指向公共类的指针
inline Car *q_func() { return q_ptr; } // 获取非const的公共类指针
inline const Car *q_func() const { return q_ptr; } // 获取const的公共类指针
public:
CarPrivate(Car *q) : q_ptr(q) {}
bool engineStarted = false; // 私有成员变量
};
Car.cpp
#include "Car.h"
#include "CarPrivate.h"
// 构造函数
Car::Car(QObject *parent) : QObject(parent), d_ptr(new CarPrivate(this)) {
// 初始化私有类
}
// 析构函数
Car::~Car() {
delete d_ptr; // 删除私有类
}
// startEngine 方法
void Car::startEngine() {
// Q_D 宏展开
// 原始宏定义:
// #define Q_D(Class) Class##Private *const d = d_func()
CarPrivate *const d = d_func(); // 获取私有实现指针
d->engineStarted = true; // 修改私有成员变量
}
Q_DECLARE_PRIVATE
// 原始宏定义:
// #define Q_DECLARE_PRIVATE(Class) \
// inline Class##Private* d_func() { return reinterpret_cast(qGetPtrHelper(d_ptr)); } \
// inline const Class##Private* d_func() const { return reinterpret_cast(qGetPtrHelper(d_ptr)); } \
// friend class Class##Private;
inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取非const的私有实现
inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取const的私有实现
friend class CarPrivate; // 声明私有实现类为友元类
d_func()
:提供了一个方法来访问私有实现类的指针。friend class CarPrivate
:将私有实现类声明为友元类,允许它访问公共类的私有成员。Q_DECLARE_PUBLIC
// 原始宏定义:
// #define Q_DECLARE_PUBLIC(Class) \
// Class *q_ptr; \
// inline Class *q_func() { return q_ptr; } \
// inline const Class *q_func() const { return q_ptr; }
Car *q_ptr; // 指向公共类的指针
inline Car *q_func() { return q_ptr; } // 获取非const的公共类指针
inline const Car *q_func() const { return q_ptr; } // 获取const的公共类指针
q_ptr
:在私有实现类中声明一个指向公共类的指针。q_func()
:提供了一个方法来访问公共类的指针。Q_D
// 原始宏定义:
// #define Q_D(Class) Class##Private *const d = d_func()
CarPrivate *const d = d_func(); // 获取私有实现指针
Q_D
:简化代码,通过 d_func()
获取私有实现类的指针,并将其存储在局部变量 d
中。Car
的头文件#include
class CarPrivate; // 前置声明私有类
class Car : public QObject {
Q_OBJECT
// Q_DECLARE_PRIVATE 宏展开
inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取非const的私有实现
inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取const的私有实现
friend class CarPrivate; // 声明私有实现类为友元类
public:
Car(QObject *parent = nullptr);
~Car();
void startEngine(); // 公共方法
private:
CarPrivate *d_ptr; // 指向私有实现类的指针
};
CarPrivate
的头文件#include "Car.h"
class CarPrivate {
// Q_DECLARE_PUBLIC 宏展开
Car *q_ptr; // 指向公共类的指针
inline Car *q_func() { return q_ptr; } // 获取非const的公共类指针
inline const Car *q_func() const { return q_ptr; } // 获取const的公共类指针
public:
CarPrivate(Car *q) : q_ptr(q) {}
bool engineStarted = false; // 私有成员变量
};
Car.cpp
#include "Car.h"
#include "CarPrivate.h"
// 构造函数
Car::Car(QObject *parent) : QObject(parent), d_ptr(new CarPrivate(this)) {
// 初始化私有类
}
// 析构函数
Car::~Car() {
delete d_ptr; // 删除私有类
}
// startEngine 方法
void Car::startEngine() {
// Q_D 宏展开
CarPrivate *const d = d_func(); // 获取私有实现指针
d->engineStarted = true; // 修改私有成员变量
}
d_ptr
:通过 Q_DECLARE_PRIVATE
宏声明,是一个指向私有实现类的指针。d_func()
:通过 Q_DECLARE_PRIVATE
宏定义,用于获取私有实现类的指针。Q_D
:简化代码,通过 d_func()
获取私有实现类的指针,并存储在局部变量 d
中。Q_DECLARE_PRIVATE
宏的定义Q_DECLARE_PRIVATE
宏的定义如下:
#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;
假设我们有一个类 Car
,其私有实现类为 CarPrivate
。使用 Q_DECLARE_PRIVATE(Car)
宏后,代码会展开为:
inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取非const的私有实现
inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取const的私有实现
friend class CarPrivate; // 声明私有实现类为友元类
d_ptr
的作用在 Q_DECLARE_PRIVATE
宏中,d_ptr
是一个特定的变量名,它被用来存储指向私有实现类的指针。Q_DECLARE_PRIVATE
宏生成的代码依赖于 d_ptr
,因为它假设类中有一个名为 d_ptr
的成员变量。
d_ptr
改为 fadsfdas_ptr
如果你将 d_ptr
改为 fadsfdas_ptr
,Q_DECLARE_PRIVATE
宏生成的代码将无法正确工作,因为宏生成的代码仍然会尝试访问 d_ptr
,而不是 fadsfdas_ptr
。
class Car : public QObject {
Q_OBJECT
// Q_DECLARE_PRIVATE 宏展开
inline CarPrivate* d_func() { return reinterpret_cast<CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取非const的私有实现
inline const CarPrivate* d_func() const { return reinterpret_cast<const CarPrivate *>(qGetPtrHelper(d_ptr)); } // 获取const的私有实现
friend class CarPrivate; // 声明私有实现类为友元类
public:
Car(QObject *parent = nullptr);
~Car();
void startEngine(); // 公共方法
private:
CarPrivate *fadsfdas_ptr; // 指向私有实现类的指针
};
d_func()
方法仍然尝试访问 d_ptr
,但 d_ptr
不存在。Q_DECLARE_PRIVATE
宏生成的代码依赖于 d_ptr
,而不是 fadsfdas_ptr
。如果你需要使用不同的变量名(例如 fadsfdas_ptr
),你需要手动实现类似 Q_DECLARE_PRIVATE
的功能。这可以通过自定义宏来完成,但不推荐,因为这会增加代码的复杂性和维护难度。
#define Q_DECLARE_PRIVATE_EX(Class, PtrName) \
inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(PtrName)); } \
inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(PtrName)); } \
friend class Class##Private;
class Car : public QObject {
Q_OBJECT
Q_DECLARE_PRIVATE_EX(Car, fadsfdas_ptr) // 使用自定义宏
public:
Car(QObject *parent = nullptr);
~Car();
void startEngine(); // 公共方法
private:
CarPrivate *fadsfdas_ptr; // 指向私有实现类的指针
};
Q_DECLARE_PRIVATE
宏的依赖Q_DECLARE_PRIVATE
宏依赖于 d_ptr
,因为它假设类中有一个名为 d_ptr
的成员变量。这个变量名是固定的,宏生成的代码会直接使用它。
d_func()
方法d_func()
方法通过 qGetPtrHelper(d_ptr)
提取 d_ptr
的原始指针,并将其转换为 CarPrivate *
类型。如果 d_ptr
不存在,d_func()
方法将无法正确工作。
friend class CarPrivate
friend class CarPrivate
声明私有实现类为友元类,允许它访问公共类的私有成员。这个声明与 d_ptr
的名字无关,但它是 Q_DECLARE_PRIVATE
宏的一部分。
Q_DECLARE_PRIVATE
宏依赖于 d_ptr
:它生成的代码假设类中有一个名为 d_ptr
的成员变量。d_ptr
改为其他名称(例如 fadsfdas_ptr
),宏生成的代码将无法正确工作。d_ptr
:为了保持代码的一致性和可维护性,建议使用默认的 d_ptr
。