参考自:函数实现不放在头文件的缘由,及什么时候能够放头文件的状况(绿色冰点)html
对于C/C++咱们很早就被告知不要在头文件里定义函数,这样很差。今天学习Skynet时,发现里面有不少函数都定义在头文件里?非常疑问,因而有了这篇文章。函数
把函数定义在头文件有哪些主要缺点?学习
一、不利于代码理解和维护:
一般,头文件被用来惟一指定接口,且多少提供一些文档来讲明如何使用在该文件中声明的组件。若把全部变量和函数的定义都写在头文件中,每每头文件异常的大,不利于代码理解;推荐把不一样功能的函数分布在不一样的源文件中,共享一个头文件;
二、函数细节在头文件中被暴露;spa
三、致使连接冲突:
头文件被多个源文件包含,头文件里的函数,变量在连接时发生冲突;
四、增长编译时间:
头文件被包含到多个源文件中,该头文件就会被编译到多个源文件里,增长了编译时间,也增大了执行程序的体积。相比之下,若是函数的实如今源文件里,而源文件则单独编译一份。(在C和C++中有个例外,即内联函数。内联函数一般放在头文件中,由于大多数实现若是不知道其定义,在编译时便没法适当的展开内联函数。)code
若是看重缺点2,则应该在第一时间放弃在头文件中定义函数。htm
缺点3是能够克服的。以下一段代码:blog
#ifndef _A_H_ #define _A_H_ int gint = 0; int myAdd(const int a, const int b) { return a + b; } #endif
解决的途径:一个是 inline(注意:在C下,内联通常使用 static inline) ,另外一个是 static 。使用这两个关键字的任意一个来修饰全局函数,都会消除上述的冲突问题,然而本质却大不相同。
若是使用 inline ,则意味着编译器会在调用此函数的地方把函数的目标代码直接插入,而不是放置一个真正的函数调用,实际做用就是这个函数事实上已经再也不存在,而是像宏同样被就地展开了。使用 inline 的反作用,首先在于毋庸置疑地,代码的体积变大了;其次则是,这个关键字严格算起来并非 C 语言的关键字,使用它多少会带来一些移植性方面的风险,尽管主流的 C 语言编译器均可以支持 inline 。对于 GCC , inline 功能关键字就是 inline 自己,而对于微软的编译器,应该是 __inline (注意有两个前导下划线)。并且,根据惯例, inline 一般都是对编译器的某种暗示而非强制要求,编译器有权力在你不知情的状况下把它实现为非 inline 的状态(可能的缘由有,函数太大或者复杂度太高)。这样的后果不是咱们愿意的。
若是使用 static ,那么至少结果是可预料的。全部包含此头文件的源文件中都会存在此函数的一份副本。虽然代码也有必定程度的膨胀,但好就好在互相不冲突,由于 static 关键字保证了该函数的可见度为单个源文件以内。注意:该方法对于全局变量来讲是毁灭性的,由于变量也只是在单个源文件里可见!
a.h接口
#ifndef _A_H_ #define _A_H_ static int gint = 0; static int myAdd(const int a, const int b) { return a + b; } #endif
#include "a.h" #include <stdio.h> int funcA() { printf("%d from A\n", gint); gint++; printf("%d from A\n", gint); return myAdd(1, 2); }
b.c文档
#include "a.h" #include <stdio.h> int funcB() { printf("%d from B\n", gint); return myAdd(1, 2); }
main.cget
#include <stdio.h> extern int funcA(); extern int funcB(); int main() { printf("%d %d\n", funcB(), funcA()); return 0; }
输出以下:
0 from A 1 from A 0 from B 3 3
可是:参见知乎上的大牛说法static函数在头文件中定义有什么好处么?,函数定义在头文件仍是慎用。
以上的讨论虽然看起来主要聚焦在 C 语言上,但因为 C++ 是 C 语言的超集,而且在这些方面并无作太多的修改,所以讨论结果一样也适用于 C++ 。对于C++能够进一步讨论,参见本文的文献。