玖叶教程网

前端编程开发入门

Effective C++ 第三十一条 Minimize compilation dependencies (略)

将文件间的编译依存关系降至最低

新手写C++的时候,可能会喜欢把所有函数放在一个文件下,显得功能又大又全,又或者是在写类的时候弄很多成员函数,其实这样对于经常修改的代码来说不好。现在给出单文件编译和多文件编译的例子,分别进行对比。

单文件:

// file xx.h
void fun1(){...}
void fun2(){...}

// xx.cpp
// 关于 fun1 和 fun2 的实现

// main.cpp
#include "xx.h"
int main(){
	...
	return 0;
}

多文件:

//file 1
void fun1(){...}

//file 2
void fun2(){...}

// main.cpp
#include "f1.h" //如果需要用到 fun1
#include "f2.h" //如果需要用到 fun2
int main(){
	...
	return 0;
}

如果采用单文件,fun1 和 fun2 即使毫无关系也被聚合在一起了,因为一旦 fun1 修改,整个 xx.h 都要重新编译,即使 fun2 没有修改也和 fun1 毫无关系。在大型项目下,会产生冗余的编译时间,浪费时间。如果采取多文件,fun1 修改只需要重新编译 f1.c 就可以了,关于 fun2 的内容无需修改。所以对于经常重新编译的 main.cpp 来说,不放入函数是非常有必要的。

但是采取多文件系统也会有一些新手难以解决的问题

// B.h
class B{
public:
	void fun(){...}
private:
	A a;
	int val;
};

这里无法编译通过,因为 a 的类型A是什么,编译器不知道。所以必须包括 A.h 这个头文件,这就将B.h 和 A.h 强行绑定了,因为 B 在创建的时候编译器必须知道类型 B 所占空间,那么就必须得到 A 的定义式才可以。如果所有文件都是这样相互联结,那么许多项目可能为了使用一个很小的功能就要包含非常多的头文件,而且编译还要带上.c文件。这就是巨大的灾难。

有一个很好的办法就是用指针代替对象

#include "A.h"
class B{
public:
	void fun(){...}
private:
	A* pa;
	int val;
};

这样就不需要知道 A 到底多大,只需要引入一个 A.h 头文件就可以编译通过,当然如果你需要使用 A 的功能那么还是需要编译的时候带上 A.c 文件进行编译。但是如果我们只进行关于 val 的操作而不进行关于 A 的操作,哪怕编译的时候不加 A.c 文件也无关紧要,而且这样做更加节省空间。假如用的不是指针而是对象,我们在B中是要包含A的,一般来说开销肯定大于一个指针的开销(8 Bytes)。这种方法叫做 handles classes。在之前的章节有所介绍。

还有一种办法叫做 interface classes。就是采用一个抽象类(java的说法)创建接口,不具体实现

// person.h 
class person;

// person.c
class person{
public:
	virtual ~person(){}
	virtual void op() const = 0;
};

这样的 person 无法使用其 object,只能使用 reference。这种好处就是使得接口和实现分离,降低了编译的耦合度。person 可以派生出多了类,这些类需要重载 op 函数。如果 op 函数实现细节修改了,person.c 文件是不需要重新编译的,除非 person 的接口都改变了。

采用 handles classes 和 interface classes 也会有缺陷,在 handles classes 上成员函数需要通过 implementation pointer获取对象数据,这就造成了一次多的间接访问,还要进行动态分配内存。可能会出现分配失败的错误,即使分配成功也要承受额外开销。如果采取 interface classes,每一个 派生类需要为 interface class 在原本的内存开销上增加一个 vptr (virtual table pointer),如果有其他 virtual 函数还要多增加其他的虚函数指针。造成内存开销变大。(条款 7 有所介绍)

总结:

  • 支持编译依存性最小的构想是,依托于声明式,不依托于定义式,两个手段是 handles classes 和 interface classes。
  • 头文件中应该完全仅有声明式

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言