基于g指针,d指针的数据隐藏

来自Qt源码中有关g指针和d指针的相关代码实例:

// 第一段
class Q_CORE_EXPORT QCoreApplication
#ifndef QT_NO_QOBJECT
: public QObject
#endif
{
……
Q_DECLARE_PRIVATE(QCoreApplication)
public:
……
~QCoreApplication();
……
protected:
QCoreApplication(QCoreApplicationPrivate &p);
#ifdef QT_NO_QOBJECT
QScopedPointer<QCoreApplicationPrivate> d_ptr;
#endif
};


//第二段
template <typename T> static inline T *qGetPtrHelper(T *ptr) { return ptr; }
template <typename Wrapper> static inline typename Wrapper::pointer\
qGetPtrHelper(const Wrapper &p) { return p.data(); }
#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;

//发现这个展开后引入了d_func()这个函数。但是“d指针”和这个宏又有什么关系呢?
//那就要说到另一个 宏“Q_D”看如下的代码

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

//从代码中可知,d_func()和d指针是紧密联系的。在Qt源码中“d_func()函数”和“d指针”的使用无处不在!
//在接下的过程中又发现了另一组宏“Q_DECLARE_PUBLIC、Q_Q”,代码如下:

#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;
#define Q_Q(Class) Class * const q = q_func()


 这个是pimpl模式,Qt广泛使用。简而言之,就是不让你知道这个类的私有成员是怎样的,有利于信息的隐藏以及高低版本的兼容。

下面给出一个本人的实验:

// 首先模仿QT声明一些宏定义
#ifndef MACRO_H_
#define MACRO_H_

#ifndef DELETE_PTR
#define DELETE_PTR(p){if(p){delete(p);(p)=nullptr;}}
#endif 

template <typename T>
static inline T* getPtrHelper(T* ptr)
{
	return ptr;
}

#define GX_DECLARE_PRIVATE(Classname) \
	inline Classname##Private * d_func() { return reinterpret_cast<Classname##Private *>(getPtrHelper(d_ptr)); } \
	inline const Classname##Private * d_func()const { return reinterpret_cast<const Classname##Private *>(getPtrHelper(d_ptr)); } \
	friend class Classname##Private;

#define GX_DECLARE_PUBLIC(Classname) \
	inline Classname * d_func() { return static_cast<Classname *>(getPtrHelper(g_ptr)); } \
	inline const Classname * d_func()const { return static_cast<const Classname *>(getPtrHelper(g_ptr)); } \
	friend class Classname;

#define D(Classname) Classname##Private * const d = d_func()

#define G(Classname) Classname * const g = g_func()

#endif

下面的代码是相关的实现:

#ifndef BOSS_H_
#define BOSS_H_
#include <string>
class BossPrivate;
// 声明一个基类
class Boss
{
public:
	Boss(BossPrivate* d = nullptr);
	virtual ~Boss();
	inline BossPrivate* getPrivate(){ return d_ptr; }

protected:
	void setPrivate(BossPrivate* bossPrivate);
	BossPrivate* d_ptr;  // d_ptr很重要
};

class BossPrivate
{
public:
	BossPrivate();
	BossPrivate(const BossPrivate& bp);
	virtual ~BossPrivate();
	Boss* g_ptr;  // g_ptr很重要
};

#endif

#include "Boss.h"
#include "Macro.h"
Boss::Boss(BossPrivate* d) : d_ptr(d)
{
	if (!d_ptr)
	{
		d_ptr = new BossPrivate;
	}
	setPrivate(d_ptr);
}

Boss::~Boss()
{
	DELETE_PTR(d_ptr);
}

void Boss::setPrivate(BossPrivate* bossPrivate)
{
	if (!bossPrivate || bossPrivate == d_ptr)
		return;

	DELETE_PTR(d_ptr);

	d_ptr = bossPrivate;

	d_ptr->g_ptr = this;
}

BossPrivate::BossPrivate() :g_ptr(nullptr)
{
}

BossPrivate::BossPrivate(const BossPrivate& bp)
{
	if (this != &bp)
		g_ptr = bp.g_ptr;
}

BossPrivate::~BossPrivate()
{
	DELETE_PTR(g_ptr);
}

基于基类的子类的实现:

#include "Macro.h"
#include "Boss.h"

class SalaryPrivate;

class Salary : public Boss
{
public:
	Salary(double x1, double x2, double x3);

	~Salary();

	double calTrueSalary();

private:
	GX_DECLARE_PRIVATE(Salary);  // 数据成员完全隐藏,
};

// 数据隐藏后的实现,
#include "CalSalary.h"

class SalaryPrivate : BossPrivate
{
	GX_DECLARE_PUBLIC(Salary);
public:
	SalaryPrivate(double x1, double x2, double x3)
	{
		_salary = new Salary(x1, x2, x3);
		_sum = x1 + x2 + x3;
	}

private:
	Salary* _salary;
	double _sum;

};

Salary::Salary(double x1, double x2, double x3) : Boss(new SalaryPrivate(x1,x2,x3))
{
}

Salary::~Salary()
{
	D(Salary);
	DELETE_PTR(d->_salary);
}

double Salary::calTrueSalary()
{
	D(Salary);
	return d->_sum;
}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值