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呢?? 首先,一個程式編譯過程如下:

compliation process

這裡的 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;
}
  1. 宣告(declare)和定義(define)的分別,也是一個很好的課題
  2. include
  3. Preprocessor
  4. compiler
  5. Object files
  6. Linker
  7. Executable
  8. 或者是警告(warning)
  9. 這裡的是指Free Function,而不是Member Method
  1. 5 Responses to “Keyword Static (Function) [C++ 求生筆記]”

  2. 但是想不到甚麼實際情況下才會把 static function 定義在 header file 裡。如果定義的內容是一樣的話,不就會有重複的執行碼嗎?

    只想到如果那 function 內引用了 macro(s),而那些 macro(s) 在不同的 compilation unit 裡有不同的定義。

    我覺得常見的錯誤反而是忘記在 cpp 裡的 free function 加上 static。

    By Milo on Apr 9, 2008

  3. 我就是看到公司的代碼有這樣的錯誤才寫下:)

    1
    2
    3
    4
    5
    6
    
    class TSystem;  // This class is a singleton class
     
    TSystem* System()
    {
      return TSystem::GetInstance();
    }

    By rdescartes on Apr 9, 2008

  4. 現在的 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 [email protected] on Jun 11, 2008

  5. 對呀,我也開始使用 unnamed namespace 了,這一文其實重點是說 internal linkage,我想若連static 的internal linkage 方面不大清楚,那麼也不必談 unnamed namespace 吧,所以在這裡就沒有說了 :)

    By rdescartes on Jun 11, 2008

  6. 很努力的教育下一代阿. 越來越多人忽略了這些基礎知識, 盼 C++ 求生筆記可幫上一把.

    By mtlung on Jul 13, 2008

Post a Comment