通常,我們在編寫c/c++代碼時,使用宏定以
#ifndef _xxx_H_
#define _xxx_H_
的方式來避免頭文件的重復包含。但是,有些情況下還會出現函數重定義的錯誤,總結原因可以歸結為:在頭文件中定義了非內聯函數。
對每個包含指定頭文件的cpp文件來說,最終都要編譯生成一個有這個非內聯函數的實體obj文件。如果一個工程中,有多個cpp文件包含了這個頭文件,在鏈接的時候就會產生多個這個非內聯函數的實體obj文件,這時,就會報重定義的錯誤。
為了避免這樣的情況,我們在定義頭文件的時候,遵循兩個原則:
- 類型定義,數據類型定義等不需要分配內存的代碼放在xxxx.h中,但是像變量定義這類需要分配內存的代碼,比如類對象的定義,需要新建一個對應的xxxx.cpp,然后把對象定義放在該cpp文件中。遵循這個原則,那么函數聲明,類型定義等等可以放在xxxx.h中,但是函數定義,變量定義則需要放在xxxx.cpp中。
- 內聯函數如果跨文件調用,必須放在頭文件中。這是因為內聯函數會在任何調用它的地方展開。所以,不會出現鏈接時重定義的錯誤。內聯展開是在編譯時進行的,只有鏈接的時候源文件之間才有關系。所以內聯要想跨源文件必須把實現寫在頭文件里。如果一個inline函數會在多個源文件中被用到,那么必須把它定義在頭文件中。因此,內聯函數一般只會用在函數內容非常簡單的時候用。
