Keyword Static (Function) [C++ 求生筆記]
April 7, 2008 – 12:15 pm有一些 C 的語法,在 C++ 的程序員相對少用。但就是因為這個原因,有時就會忽略了。
假設我們有一個Header檔 Foo.h:
1 2 3 4 5 6 7 8 9 10 | static void f1() { std::cout << "f1()" << std::endl; } void f2() { std::cout << "f2()" << std::endl; } |
f1 和 f2 的分別在於 static 這個 keyword 。在這裡的 f1 被宣告和定義(declare)1為 static ,是指它只在這個Compilation Unit中生效。而 f2 沒有被定義為 static ,亦即是它可以被其他 Compilation Unit 訪問。
但到底什麼是 Compilation Unit呢?? 首先,一個程式編譯過程如下:
這裡的 a.cpp , b.cpp 和 c.cpp 也 引入2了Foo.h 這個檔案,經過預處理器3後,Foo.h的內容會被加入到 a.cpp, b.cpp 和 c.cpp 中,再經過編譯器4,變成為 a.o , b.o 和 c.o 這些目的碼5,最後經過連結器6,變成執行檔7。
要留意的地方是,每個經過預處理器處理後的.cpp 檔,和它的目的檔是一一對應的,而Compilation Unit,就是這些被處理後的.cpp 檔了。
若以Foo.h 的 f1 為例子,雖然在每個 .cpp 檔也被定義了,但經過編譯後,所有的f1 也會被隱藏在自己的目的檔中,連結器在找尋symbol的過程中,是會忽略的。
但f2 就不同了,所有的f2 在目的檔中,也是不會被隱藏,所以在連結器找尋symbol,會找到多份的f2,那就會有連結器錯誤8 了。
所以在大部份的情況下,在Header檔中定義函數9,也是需要static 這個keyword 的。就算加上了inline,情況也是一樣的。
1 2 3 4 | static inline void f3() { std::cout << "f3() is called" << std::endl; } |
5 Responses to “Keyword Static (Function) [C++ 求生筆記]”
但是想不到甚麼實際情況下才會把 static function 定義在 header file 裡。如果定義的內容是一樣的話,不就會有重複的執行碼嗎?
只想到如果那 function 內引用了 macro(s),而那些 macro(s) 在不同的 compilation unit 裡有不同的定義。
我覺得常見的錯誤反而是忘記在 cpp 裡的 free function 加上 static。
By Milo on Apr 9, 2008
我就是看到公司的代碼有這樣的錯誤才寫下:)
By rdescartes on Apr 9, 2008
現在的 C++ 已經鼓勵用 unnamed namespace 代替 static 修飾 free function 以及 global (lifetime) instance.
原因有三:
1. static 一個 keyword 同時俱備過多功能.
2. static 的 free function 以及 instance 是 internal linkage. 不能拿來當作 template parameter.
3. unnamed namespace 不但可用在 static 的 free function 以及 instance 上, 也可用在 class/struct 上. 是一個統一的作法.
By fr3@K on Jun 11, 2008
對呀,我也開始使用 unnamed namespace 了,這一文其實重點是說 internal linkage,我想若連static 的internal linkage 方面不大清楚,那麼也不必談 unnamed namespace 吧,所以在這裡就沒有說了 :)
By rdescartes on Jun 11, 2008
很努力的教育下一代阿. 越來越多人忽略了這些基礎知識, 盼 C++ 求生筆記可幫上一把.
By mtlung on Jul 13, 2008