考虑这样几个类,A、a1、a2、B,其中A和B是要暴露给用户的类。
1.最初组织关系如下:
//a1.h
#include <iostream>
class a1
{
public:
void DoSomething()
{
std::cout<<"a1 do sth"<<std::endl;
}
};
//a2.h
#include <iostream>
class a2
{
public:
void DoSomething()
{
std::cout<<"a2 do sth"<<std::endl;
}
};
//B.h
#include <iostream>
class B
{
public:
void DoSomething()
{
std::cout<<"B do sth"<<std::endl;
}
};
//A.h
#include "a1.h"
#include "a2.h"
#include "B.h"
class A
{
public:
void DoSomething();
B ReturnB();
private:
a1 _a1;
a2 _a2;
};
//A.cpp
#include "A.h"
void A::DoSomething()
{
_a1.DoSomething();
_a2.DoSomething();
}
B A::ReturnB()
{
return B();
}
//user.cpp
#include "A.h"
int main()
{
A a;
a.DoSomething();
a.ReturnB().DoSomething();
}
因此,user.cpp 中直接或间接的include了A.h B.h a1.h a2.h,而且user根本不知道已经include了 这么多.h,尤其是不知道已经include了B.h。因此,如果与接口无关类型a1.h和a2.h改变了,会导致user.cpp重新编译。
2.利用指针/引用进行实现之:
a1.h a2.h B.h不用更改。
//A.h
class a1;
class a2;
class B;
class A
{
public:
void DoSomething();
B ReturnB();
private:
a1 *_a1;
a2 *_a2;
};
//A.cpp
#include "A.h"
#include "a1.h"
#include "a2.h"
#include "B.h"
void A::DoSomething()
{
_a1 = new a1();
_a1->DoSomething();
delete _a1;
_a2 = new a2();
_a2->DoSomething();
delete _a2;
}
B A::ReturnB()
{
return B();
}
//user.cpp
#include "A.h"
#include "B.h"//显示指明我要你
int main()
{
A a;
a.DoSomething();
B b = a.ReturnB();b.DoSomething();
}
//此时user.cpp只是包含了A.h 和 B.h,因此a1.h和a2.h修改的时候,user.cpp不用再重新编译。但是user可以看到A.h里含有a1,a2这些毫无意义的东西,这样的话,是暴露了其内部实现,因此我们纳入一个新的类AImpl来消灭这个暴露狂。
3.实现AImpl,将A变成一个Handle class
a1.h a2.h B.h不变。
//AImpl.h //真是臃肿,懒得写AImpl.cpp了
#include "a1.h"
#include "a2.h"
#include "B.h"
class AImpl
{
public:
void DoSomething()
{
_a1.DoSomething();
_a2.DoSomething();
}
B ReturnB()
{
return B();
}
private:
a1 _a1;
a2 _a2;
};
//A.h
class AImpl;
class B;
class A
{
public:
void DoSomething();
B ReturnB();
private:
AImpl *aImpl;
};
//A.cpp
#include "A.h"
#include "AImpl.h"
#include "B.h"
void A::DoSomething()
{
aImpl->DoSomething();
}
B A::ReturnB()
{
return aImpl->ReturnB();
}
//user.cpp不变,但是这次他看到的A.h就没有_a1和_a2这些东西了~~~~
以上这类方法叫做Handle class,不过我怎么觉得没什么大用啊,c++标准库里有应用吗?谁知道,麻烦告诉小弟声~~~
另外Effective C++里还有另外一种方法,叫做Protocal class,相貌如下:
class AProtocal
{
A *makeA();
void DoSomething();
B ReturnB();
}
所以实现也就不言自明了,另外比较高级的实现方法,就是将A public继承一个接口类,并private 继承一个实现类,具体见书本吧。