C++程序设计机制:pimpl机制

1、pimpl机制的作用

pimpl(private implementation)其主要作用是解开类的使用接口和实现的耦合。

关于耦合性:耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。

模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差。

软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。

2、pimpl机制的实现思想

pimpl(private implementation)的思想是将私有的数据和函数放入一个单独的类中,并保存在一个实现文件中,然后在使用它的头文件中对这个类进行前置类型声明,并定义一个指向该实现类的指针。类的构造函数分配这个pimpl类,而析构函数则释放它。这样可以解开类的使用接口和实现的耦合。

3、实际项目开发遇到的问题

有时候需要修改某个类的实现,而这样的修改会导致所有包含该类的代码需要重新编译,当这个类在项目中被大量使用时,那么编译时间是很长的;别人使用“不合法的方法”调用了我们编写的接口,突破了我们期望给予的限制。

使用pimpl能给我们带来的好处:
1.将具体类的实现封装到另一个类中,使用者只能看到一个前置类型声明和对应的指针。除非使用者去修改对应的实现,否则,他将无法知道具体的实现,也就无法通过一些非法的方式去访问。从一定程度上防止了封装的泄漏;
2.同时类与数据成员之间的耦合最低,类看起来总是一个样子,包含该类声明的文件也不会因为类实现的改变而重新编译,节约编译时间。

4、案例:暴露私有实现

cmessage.h:

#ifndef __MESSAGE_H__
#define __MESSAGE_H__

#include <string>

class CMessage
{
public:
CMessage(std::string strWarn);
~CMessage();
void printf();

private:
std::string m_strWarnMsg;
};

#endif //#ifndef __MESSAGE_H__

这是一个消息类,提供消息打印方法。

但是当我们提供该头文件的时候,其实已经暴露了私有的实现。

5、案例:修改实现,导致大量源文件重新编译

cmessage.h:

#ifndef __MESSAGE_H__
#define __MESSAGE_H__

#include <string>

class CMessage
{
public:
CMessage(std::string strWarn);
~CMessage();
void printf();

private:
std::string m_strWarnMsg;
std::string m_strAdditionMsg;//新功能
};

虽然之前的接口没有改变,但是项目中使用到该头文件的所有源码文件都需要重新编译。

6、案例:使用pimpl思想重新设计模块

使用上面提到的pimpl(private implementation)的思想。我们重新设计该类的实现。

cmessage.h:

#ifndef __MESSAGE_H__
#define __MESSAGE_H__

#include <string>

class CMessagePrivate;//实现类前置类型声明
class CMessage
{
public:
CMessage(std::string strWarn);
~CMessage();
void printf();

private:
CMessagePrivate * const d;//实现类指针
};
#endif //#ifndef __MESSAGE_H__

cmessage.cpp:

#include "cmessage.h"
#include "cmessage_p.h"

CMessage::CMessage(std::string strWarn):d(new CMessagePrivate(strWarn))
{
	
}

CMessage::~CMessage()
{
	delete d;
}

void CMessage::printf()
{
	d->printf();
}

cmessage_p.h:

#ifndef __MESSAGE_P_H__
#define __MESSAGE_P_H__

#include <string>

class CMessagePrivate
{
public:
CMessagePrivate(std::string strWarn);
~CMessagePrivate();
void printf();

private:
std::string m_strWarnMsg;
std::string m_strAdditionMsg;
int m_fileNo;
};

#endif //#ifndef __MESSAGE_P_H__

cmessage_p.cpp:

#include "cmessage_p.h"
#include <iostream>


CMessagePrivate::CMessagePrivate(std::string strWarn):m_strWarnMsg(strWarn),m_strAdditionMsg(__FILE__),m_fileNo(__LINE__)
{
	
}

CMessagePrivate::~CMessagePrivate()
{

}

void CMessagePrivate::printf()
{
	std::cout << m_strWarnMsg << std::endl;
	std::cout << m_strAdditionMsg << ":" << m_fileNo << std::endl;
}

此时,CMessage类还是提供同样的接口printf,只是该接口的实现放到了CMessagePrivate类中实现了,对于使用者毫不知情。

还有,在CMessagePrivate类中任何新加的功能,都只会影响到CMessagePrivate.cpp和CMessage.cpp,任何包含cmessage.h文件的源文件都不需要重新编译,大大节省了项目编译的时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉淀期待未来9527

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值