2014-04-29 60 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() { ... }