分类:
2008-10-15 16:40:38
在用写要导出类的库时,我们经常只想暴露接口,而隐藏类的实现细节。也就是说我们提供的头文件里只提供要暴露的公共成员函数的声明,类的其他所有信息都不会在这个头文件里面显示出来。这个时候就要用到接口与实现分离的技术。
下面用一个最简单的例子来说明。
类ClxEXP是我们要导出的类,其中有一个私有成员变量是ClxTest类的对象,各个文件内容如下:
lxTest.h文件内容:
class ClxTest
{
public:
ClxTest();
virtual ~ClxTest();
void DoSomething();
};
lxTest.cpp文件内容:
#include "lxTest.h"
#include
using namespace std;
ClxTest::ClxTest()
{}
ClxTest::~ClxTest()
{}
void ClxTest::DoSomething()
{
cout << "Do something in class ClxTest!" << endl;
}
////////////////////////////////////////////////////////////////////////////
lxExp.h文件内容:
#include "lxTest.h"
class ClxExp
{
public:
ClxExp();
virtual ~ClxExp();
void DoSomething();
private:
ClxTest m_lxTest;
void lxTest();
};
lxExp.cpp文件内容:
#include "lxExp.h"
ClxExp::ClxExp()
{}
ClxExp::~ClxExp()
{}
// 其实该方法在这里并没有必要,我这样只是为了说明调用关系
void ClxExp::lxTest()
{
m_lxTest.DoSomething();
}
void ClxExp::DoSomething()
{
lxTest();
}
为了让用户能使用我们的类ClxExp,我们必须提供lxExp.h文件,这样类ClxExp的私有成员也暴露给用户了。而且,仅仅提供lxExp.h文件是不够的,因为lxExp.h文件include了lxTest.h文件,在这种情况下,我们还要提供lxTest.h文件。那样ClxExp类的实现细节就全暴露给用户了。另外,当我们对类ClxTest做了修改(如添加或删除一些成员变量或方法)时,我们还要给用户更新lxTest.h文件,而这个文件是跟接口无关的。如果类ClxExp里面有很多像m_lxTest那样的对象的话,我们就要给用户提供N个像lxTest.h那样的头文件,而且其中任何一个类有改动,我们都要给用户更新头文件。还有一点就是用户在这种情况下必须进行重新编译!
上面是非常小的一个例子,重新编译的时间可以忽略不计。但是,如果类ClxExp被用户大量使用的话,那么在一个大项目中,重新编译的时候我们就有时间可以去喝杯咖啡什么的了。当然上面的种种情况不是我们想看到的!你也可以想像一下用户在自己程序不用改动的情况下要不停的更新头文件和编译时,他们心里会骂些什么。其实对用户来说,他们只关心类ClxExp的接口DoSomething()方法。那我们怎么才能只暴露类ClxExp的DoSomething()方法而不又产生上面所说的那些问题呢?答案就是--接口与实现的分离。我可以让类ClxExp定义接口,而把实现放在另外一个类里面。下面是具体的方法:
首先,添加一个实现类ClxImplement来实现ClxExp的所有功能。注意:类ClxImplement有着跟类ClxExp一样的公有成员函数,因为他们的接口要完全一致。
lxImplement.h文件内容:
[1]