[英]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.