PIMPL

PIMPL(Private Implementation 或 Pointer to Implementation)是微软的Herb Sutter提出来,它通过一个私有的成员指针,将指针所指向的类的内部实现数据进行隐藏。
先观察以下两种头文件实现方式
第一种:

#include "Animal.h"
class Test
{
public:
    void Fun();
private:
    Animal animal;//类Test与类Animal之间 是强耦合关系
};   

存在的问题:
修改Animal 的定义会导致所有使用Animal 的源文件需要重新编译
分析:
1. 在一个大型的项目中,第一种情况,Animal animal;//类Test与类Animal之间 是强耦合关系, 这种耦合可能会对编译时间产生相当大的影响。
2. 从语义上说,第一种中的animal成员数据应该属于Test的实现部分,不应该暴露给用户(.h文件提供给用户,而cpp文件不会提供给用户)
3. 编译器在编译期间需要分配的空间会随着类Animal 的大小改变而变得不确定。

第二种:

class Animal;
class Test
{
public:
    void Fun();
private:
    Animal* pAnimal;
};

PIMPL惯用手法,能够降低类之间的耦合性,分析如下:
1. 在32位平台上,指针大小是个固定值4,64位固定为8.在编译期间,编译器明确知道分配4个字节出来。
2. pAnimal是个指针,所以Animal的二进制信息(sizeof(Animal)等)不会被耦合到Test的使用接口上去,这样只要接口Fun()不变,Animal类对Test类的影响降到最低。

 #include 
#include "Animal.h"
using namespace std;
class Animal;
class Test
{
public:
    void Fun();
private:
    Animal* pAnimal;
};
int main()
{
    Test test;
    test.Fun();

   cin.get();
}

防火墙

1.PIMPL惯用手法又被成为“编译期防火墙”。C++的编译模式为“分离式编译”,即不同的源文件是分开编译的。也就是说,不同的源文件之间有一道天然的防火墙,一个源文件“失火”并不会影响到另一个源文件。

2.但是头文件呢,如果头文件“失火”又当如何呢?头文件是不能直接编译的,它包含于源文件中,并作为源文件的一部分被一起编译。这就是说头文件改变会影响到源文件,使得需要重新编译。我们常常听到诸如“不要改动公有接口”这样的建议,所以我们一般都会修改私有接口,这样Fun()接口不变的情况下,不能因为Animal类的私有成员变动影响到Test类。
3. 指针在这里充当了一座桥梁。将依赖信息“推”到了另一个编译单元,与用户隔绝开来。而防火墙是C++编译器的固有属性。

穿越C++编译期防火墙

是什么穿越了C++编译期防火墙?是指针!使用指针的源文件“知道”指针所指的是什么对象,但是不必直接“看到”那个对象——它可能在另一个编译单元,是指针穿越了编译期防火墙,连接到了那个对象。
从某种意义上说,只要是代表地址的符号都能够穿越C++编译期防火墙,而代表结构(constructs)的符号则不能。
例如函数名,它指的是函数代码的始地址,所以,函数能够声明在一个编译单元,但定义在另一个编译单元,编译器会负责将它们连接起来。用户只要得到函数的声明就可以使用它。而则不同,类名代表的是一个语言结构,使用类,必须知道类的定义,否则无法生成二进制代码。变量的符号实质上也是地址,但是使用变量一般需要变量的定义,而使用extern修饰符则可以将变量的定义置于另一个编译单元中。

本文主要参考博客,地址:http://blog.csdn.net/armman/article/details/1737719

你可能感兴趣的:(Boost库)