我们平时无意中就使用了pimpl模式,pimpl即 pointer to implementation,“指向实现的指针”缩写,主要避免在头文件中暴露私有细节,降低编译依赖,促进API接口和实现的完全分离的重要方法。
比如我们有个打印几个数据的api,
头文件pimpl_pattern.h
#ifndef __PIMPL_PATTERN_H__
#define __PIMPL_PATTERN_H__
void dump(int nA,int nB,int nC);
#endif
.c文件
pimpl_pattern.c
#include ”pimpl_pattern.h”
void dump(int nA,int nB,int nC)
{
printf("\n auto a=%d ,b=%d \n",nA,nB, nC);
}
调用形式:
dump(nA,nB,nC);
Now,我们有一个新需求,要求把第一个参数改成字符串,第一个参数改成float,
那接口岂不是得改成:
void dump(char * nA,float nB, int nC);
,当然,所有调用dump的模式都得改是不是。
使用不透明指针,即pimpl用法,通过在头文件定义不透明指针auto_pimpl_t *。
对外隐藏细节,任何时候去扩展dump函数,都不会影响外部模块对dump函数的
调用。我们可以非常方便的在.c文件去扩展auto_pimpl_t *指针的结构体成员。
头文件
pimpl_pattern.h
#ifndef __PIMPL_PATTERN_H__
#define __PIMPL_PATTERN_H__
typedef struct auto_pimpl auto_pimpl_t;
void dump(auto_pimpl_t *pAutoPimpl);
#endif
.c文件
pimpl_pattern.c
#include ”pimpl_pattern.h”
#include <stdio.h>
#include "pimpl_pattern.h"
typedef struct auto_pimpl
{
int m_nA;
int m_nB;
int m_nC;
}auto_pimpl_t;
void dump(auto_pimpl_t *pAutoPimpl)
{
if(NULL == pAutoPimpl)
{
return;
}
printf("\n auto a=%d ,b=%d c=%d \n",
pAutoPimpl->m_nA,pAutoPimpl->m_nB,pAutoPimpl->m_nC);
}
int main()
{
auto_pimpl_t AutoPimpl;
AutoPimpl.m_nA = 0;
AutoPimpl.m_nB = 2;
AutoPimpl.m_nC =4;
dump(&AutoPimpl);
return 0;
}
另外,降低#include的依赖性,
1)永远不用用#include包含不必要的头文件;
2)只需要前置声明时,绝不需要用#include包含相应的头文件;