2016-03-21 97 views
1

我有以下標題:在名稱空間中聲明和定義函數?

#ifndef MY_H_ 
#define MY_H_ 

namespace A { 
void f() { 
// do something 
} 
} 
#endif 

然而,當我編譯時,我得到了這樣的錯誤A ::的F多個定義()。我認爲#ifndef檢查足以避免1個翻譯單元中的重複定義。也許我想念什麼?

在此先感謝。

+2

你錯過了一個事實,即多個定義問題屬於對* *多個翻譯單元,而不是1翻譯單元。 –

+0

@KerrekSB感謝您的快速響應。是的,我明白你的意思。我可以將其設置爲靜態以避免該問題。內聯也適用於我的編譯器。但是因爲內聯只是編譯器的一個提示,所以編譯器可能會忽略它,我仍然會得到多個定義。或者編譯器保證在這種情況下不會忽略內聯? – Hei

+0

真正的答案是不要將定義放在標題中。那麼你沒有得到多個定義! –

回答

2

的函數定義之前添加inline符:

#ifndef MY_H_ 
#define MY_H_ 

namespace A { 
inline void f() { 
// do something 
} 
} 
#endif 
+0

內聯適用於我的編譯器。但是因爲內聯只是編譯器的一個提示,所以編譯器可能會忽略它,我仍然會得到多個定義。或者編譯器保證在這種情況下不會忽略內聯? – Hei

+0

根據上面鏈接描述中的第一點:「1)只要每個定義出現在不同的翻譯單元中,程序中可能有多個內聯函數的定義,例如,可以定義內聯函數在#包含在多個源文件中的頭文件中。「內聯作爲編譯器的優化提示現在已經過時。 – pmed

+0

感謝您的回覆。因此,您的意思是在新的C++標準(C++ 11或C++ 14)中,標準要求編譯器正確處理內聯而不是內聯作爲提示? – Hei

0

你應該在頭文件中聲明函數,但是在你的cpp文件中定義它們。如果您包含來自多個翻譯單元的這個頭文件(這是最可能的),那麼將有多個實現可用於不同的翻譯單元。包含此頭文件的每個cpp文件都將具有f的實現。這樣,如果f被調用,它是不明確的。通過將實現放入cpp文件中,可以將其鏈接和使用。但是隻有一個可用的實現可以使其明確無誤。

所以,你的頭文件應該是:

#ifndef MY_H_ 
#define MY_H_ 

namespace A 
{ 
    void f(); // declaration only 
} 

#endif 

和源文件:

#include "myHeader.h" 

namespace A 
{ 
    void f() 
    { 
     // some implementation 
    } 
} 

然後,你應該罰款。你通常會用你所有的功能來做到這一點。函數/方法或模板只有inline,但這超出了這個問題的範圍。