不要在头文件中定义有链接的实体
具有链接的实体,包括名字空间级的变量或函数,都需要分配内存,在头文件中定义这样的实体将导致连接错误或者内存浪费。所以,应该将所有具有链接的实体放入实现文件。
下面的头文件:
1 int max; 2 string hello("Hello, world!"); 3 void fun() { ... }
只要被一个以上的源文件所包含,就很容易导致链接错误,编译器会报告存在重复符合错误。原因很简单:每个源文件中,都会定义max、hello和fun的函数体,并分配空间。当进行链接的时候,链接器将面对多个具有相同名字而且互相在竞争的符号。
解决之道非常简单——只在头文件中放置声明即可:
1 extern max; 2 extern string hello; 3 void fun();
而实际的定义则放在一个实现文件中。
同样,不要在同文件中定义名字空间级的static实体,例如:
1 static int max; 2 static string hello("Hello, world!"); 3 static void fun() { ... }
这种对static的错误使用比在头文件中只定义全局实体还要危险。对于全局实体,至少链接器可能会立即发现重复,但是静态数据和函数的重复是合法的。因此,若在某个头文件中定义了静态数据和静态函数,而该头文件要被50个文件包含,那么函数体和数据所占用的空间在最终的可执行文件中会重复50次,造成内存浪费。
例外情况:
(1)内联函数。
(2)函数模版。
(3)类模板的静态数据成员。

浙公网安备 33010602011771号