【Skynet】C头文件不要定义函数?

参考自:函数实现不放在头文件的缘由,及什么时候能够放头文件的状况(绿色冰点)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

在同一工程中,两个以上的源文件包含了此头文件,则在连接时期就会发生冲突,由于在两个源文件编译获得的目标文件中都有一份 myAdd 的函数实现,连接器不知道对于调用了此函数的调用者,应该使用哪个副本。这一问题对于全局变量也是如此。


解决的途径:一个是 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



a.c

#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 确实能够解决函数的连接问题,对于全局变量则并不适合,两份变量都只在本地源文件可见。


可是:参见知乎上的大牛说法static函数在头文件中定义有什么好处么?,函数定义在头文件仍是慎用。


以上的讨论虽然看起来主要聚焦在 C 语言上,但因为 C++ 是 C 语言的超集,而且在这些方面并无作太多的修改,所以讨论结果一样也适用于 C++ 。对于C++能够进一步讨论,参见本文的文献。