在软件开发中经常需要对自己写的类进行封装,接口给外部留下,而对实现细节进行隐藏。通常是留下一个头文件,给一个lib文件和dll文件(windows下)。但是这个头文件中也可能暴露过多的信息,能不能只留下公共接口,其余有关基类的信息一点都不暴露呢?在大牛的指点下,get到了这个有用的方法,记录在此,以防忘记。
1. 通常的方法,头文件:
#ifndef CSECREAT_H
#define CSECREAT_H
class CSecreat
{
public:
CSecreat();
void myFunc(int iVariable);
virtual ~CSecreat();
private:
void myFuncHello();
void myFuncWorld();
};
#endif // !CSECREAT_H
源文件,封装成库了:
#include "CSecreat.h"
#include <iostream>
CSecreat::CSecreat()
{
}
void CSecreat::myFunc(int iVariable)
{
if (1 == iVariable)
{
myFuncHello();
}
else
{
myFuncWorld();
}
}
void CSecreat::myFuncHello()
{
std::cout << "hello!" << std::endl;
}
void CSecreat::myFuncWorld()
{
std::cout << "world!" << std::endl;
}
CSecreat::~CSecreat()
{
}
这样做,在类定义的头文件中,除了有接口外,还是暴露了实现的方法。应该进一步封装,最终只有接口出现在头文件中,其它关于类的任何细节都是看不到的。
2. 可以这样做,定义一个基类CVisible,该基类中声明接口,该基类派生一个CSecreat类,派生类对接口进行实现。基类中返回派生类的对象,供客户端使用。这样接口提供给客户端,而且具体的实现是看不到的,类的细节也看不到,封装的很棒。
基类头文件CVisible.h:
#ifndef CVISIBLE_H
#define CVISIBLE_H
class CVisible
{
public:
CVisible() {};
virtual void myFunc(int iVariable) {}; //接口函数
CVisible* getDerived();
virtual ~CVisible() {};
};
#endif
基类源文件CVisible.cpp
#include "CVisible.h"
#include "CSecreat.h"
CVisible* CVisible::getDerived()
{
return new CSecreat(); //new一个派生类的对象
}
派生类头文件CSecreat.h:
#ifndef CSECREAT_H
#define CSECREAT_H
#include "CVisible.h"
class CSecreat:public CVisible
{
public:
CSecreat();
void myFunc(int iVariable);
virtual ~CSecreat();
private:
void myFuncHello();
void myFuncWorld();
};
#endif
派生类的源文件CSecreat.cpp,同上,没有改变。
客户端调用:
#include "CVisible.h"
int main()
{
CVisible cvis;
cvis.getDerived()->myFunc(1);
return 0;
}
就这样,解决了接口封装中,头文件暴露内容过多的问题。