2014-04-29 58 views
3

我得到一個鏈接錯誤:C++:避免​​重複符號鏈接錯誤

duplicate symbol __ZN5ENDF64FileILNS_7MF_enumE1EE4readEv in: 
    Read.cpp.o 
    Material.cpp.o 

,其中重複的符號名是:

$ c++filt __ZN5ENDF64FileILNS_7MF_enumE1EE4readEv 
    ENDF6::File<(ENDF6::MF_enum)1>::read() 

我知道,我不能定義相同功能在多個地方 - 這可能會導致此鏈接器錯誤。 (我見過這個問題:ld: duplicate symbol)我不認爲我有多個地方定義的read()函數,但鏈接器(clang++)說我這樣做。

我在哪裏複製read()符號?

我的代碼結構如下:

//MFs.hpp 
#ifndef MFS_HPP 
#define MFS_HPP 
enum class MF_enum { 
... 
} 
#endif 


//File.hpp 
#ifndef FILE_HPP 
#define FILE_HPP 

#include "MFs.hpp" 

// Definition of class File 
template<> 
class File { 
... 
} 

// Definition of File<...>::read() function 
template <> 
void File<1>::read() 
{ 
    std::cout << "Reading into MF=1"<< std::endl; 
} 

#endif 

沒有File.cpp因爲File類模板。所有的定義(和聲明)是File.hpp

// Material.cpp 
#include "File.hpp" 
... 

// Material.hpp 
#ifndef MATERIAL_HPP 
#define MATERIAL_HPP 

#include "File.hpp" 
... 
#endif 

最後的驅動程序代碼:

// Read.cpp 
#include "Material.hpp" 
#include "File.hpp" 

int main(){ 
... 
} 
+3

你是否專注於文件<1> :: read()'?如果是這樣,你需要標記專業化'inline'(完整的專業化不再是一個模板,而是一個函數。[read'函數的實際定義是這個問題的核心,它不應該隱藏在評論中:'//定義文件<...> :: read()'!!!] –

+0

MFs.hpp中是否包含#include「MFs.hpp」? – Ram

+0

@Ram:如果是這種情況,並且包含守護程序不起作用,它會觸發一個編譯器,而不是鏈接器,錯誤 –

回答

7

(完成)模板的特化不是模板本身。如果您是專業的功能,那麼你需要要麼只是聲明它的頭,並提供一個單一的翻譯單元執行,否則會使這個定義內聯:

// Header [1] 
template <int> 
class File { 
    // ... 
    void open(); 
}; 
template <> 
void File<1>::open(); // just declaration 

// Single .cpp 
template <> 
void File<1>::open() { ... } 

或者:

// Header [2] 
template <int> 
class File { 
    // ... 
    void open(); 
}; 
template <> 
inline void File<1>::open() { ... }