[英]What is the reason and the meaning to use static non-member functions in C++?
当链接整个程序和从多个地方调用函数时,就会看到差异。
如果foo.cpp
和bar.cpp
都包含implementation.h
,带有static int baz() { return 0; }
static int baz() { return 0; }
,方法baz
将独立存在于foo.cpp
和bar.cpp
的编译单元中。
当方法是非静态(和非内联)时,方法baz
被认为可由知道原型的所有编译单元链接。 在这种情况下编译gcc foo.cpp bar.cpp
将导致baz
的多个引用的链接错误。
在大多数 C++ 实现中,每个.cpp
文件都被编译成对应的.o
文件。 .o
文件包含.cpp
文件功能的object 代码——即 CPU 需要执行以执行这些功能的机器代码指令。
对于非静态函数, .o
文件还包含链接器可读的元数据; 即.o
文件中存在的(损坏的)function 名称列表,这些函数位于文件中等。在链接时,linker 将使用此元数据来解析对这些函数的调用,这些函数是从在其他.cpp
文件中。
对于 static 函数,OTOH, .o
文件不包含任何元数据; 就linker而言,static功能不存在。 static 函数实际上是“秘密的”,仅可用于同一.cpp
文件中的其他代码(它不依赖于 linker 来访问 static 函数,因为它是作为同一编译单元的一部分编译的,并且可以因此直接引用它们)
在您的情况下,您在.h
文件中实现了 static function,这意味着 function 的单独副本包含在使用该 function 的每个.cpp
文件的.o
文件中,这就是为什么它仍然“有效”的原因你。
人们经常使用static
作为一种私有命名空间标记,以保证不会从它们出现的.cpp
文件外部调用函数。在 C++ 中,可以使用匿名命名空间来实现类似的结果。
正如其他人解释的那样,在 C++ 中,如果您的代码包含多个文件,那么默认情况下所有全局函数和变量都具有external linking
。 例如在文件A.cpp 中定义的A.cpp
可以通过编译器自动链接在文件B.cpp
中调用。 请记住,您必须分别编译这两个文件,稍后您将告诉编译器链接这些对象.o
文件。 编译器会将所有内容拼接在一起。 正如我在下面的Makefile
中所做的那样。
但是如果你想禁用external linking
,你将使你的 function 成为static
所以现在你的 function 或变量仅可用于声明它的文件。 这称为internal linking
。
内部链接用于你必须有全局变量的地方,但你不希望你的全局变量在这个文件之外被访问,而其他一些文件意外地修改了它。
为了更好地理解这个代码是如何工作的:
第一个.cpp
#include <iostream>
/*static*/ void hello(){ //static will not let this code compile
std::cout << "Hello I am external linking" << std::endl;
}
主.cpp
void hello();
int main(){
hello();
}
Makefile
program: first.o main.o
g++ main.o first.o -o test
main.o: main.cpp
g++ -g -c main.cpp -o main.o
first.o: first.cpp
g++ -g -c first.cpp -o first.o
这按您预期的那样工作。 但是如果你把static
放在 first.cpp 中hello()
的first.cpp
,这将变成内部链接,所以你会得到编译器的链接错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.