考虑以下代码
class A
{
public:
A() { cout << "A" << endl; }
~A() { cout << "des A" << endl; }
void output() { cout << "A" << endl; }
};
class B
{
public:
B() {}
void output() { cout << "B" << endl; }
};
class C
{
public:
C(const A & _a, const B &_b) {
a = _a;
b = _b;
}
void output() {
a.output();
b.output();
}
private:
A a;
B b;
};
由于类C中有A,B的成员对象,所以当a,b有一点改变,C类就需要重新编译,需要重新编译的原因如下。假设在main函数中
void main()
{
int x;
C c;
}
对于x编译器可以明确的知道需要分配Int大小的内存,而对于对象c也需要知道需要分配多少空间来存放,所以它就需要询问c的定义。而C中有A的对象,A被改变了,需要重新编译,那此时C就需要重新编译了。
此问题可以通过一个名为 pointer to implementation的方法来改变,即将a,b的操作否放在实现类CImpl中,而C类中存放方一个指向实现物的指针。代码如下
class CImpl
{
public:
//CImpl() {}
CImpl(const A & _a, const B &_b) {
a = _a;
b = _b;
}
void output() {
a.output();
b.output();
}
private:
A a;
B b;
};
class C
{
public:
C(const A & a, const B &b) :pImpl(new CImpl(a, b)) {}
void Output()
{
pImpl.get()->output();
}
private:
shared_ptr<CImpl> pImpl;
};
此时C中只存放了一个指针的大小,不管A,B如何改变都不影响C了
还有一种方法可将接口与实现分离,代码如下
class C
{
public:
C() {}
virtual ~C() {}
virtual void output() = 0;
static shared_ptr<C> create(const A&, const B&);
};
class RealC:public C
{
public:
RealC() {}
RealC(const A & _a, const B &_b):a(_a),b(_b)
{
}
~RealC() {}
void output()
{
a.output();
b.output();
}
private:
A a;
B b;
};
shared_ptr<C> C::create(const A&a, const B&b)
{
return shared_ptr<C>(new RealC(a, b));
}
调用时只需要C::create()->output();即可