2016-08-20 72 views
3

尽管我在所有头文件中都包含了头文件,但是当我创建头文件PointXYZRGBAI.h并将其包含在LidarFile.cpp和core.cpp,生成多个文件使用的头文件中的结构声明导致架构x86_64的重复符号

duplicate symbol _EIGEN_ALIGN_16 in: 
    CMakeFiles/core.dir/core.cpp.o 
    CMakeFiles/core.dir/LidarFile.cpp.o 
ld: 1 duplicate symbol for architecture x86_64 

错误和误差似乎标题中抱怨是

#define PCL_NO_PRECOMPILE 

#ifndef POINTXYZRGBAI_H 
#define POINTXYZRGBAI_H 
#endif 

#include <pcl/point_types.h> 

struct PointXYZRGBAI{ 
    PCL_ADD_POINT4D; 
    union{ 
    struct{ 
     float intensity; 
     uint32_t rgba; 
    }; 
    float data_c[4]; 
    }; 
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW 
} EIGEN_ALIGN_16; 

POINT_CLOUD_REGISTER_POINT_STRUCT(PointXYZRGBAI, 
            (float, x, x) 
            (float, y, y) 
            (float, z, z) 
            (float, intensity, intensity) 
            (uint32_t, rgba, rgba) 
) 

inline std::ostream& operator << (std::ostream& os, const PointXYZRGBAI& p){ 
    os << "(" << p.x << ", " << p.y << ", " << p.z << " - " << p.intensity << " - " << p.rgba << ")"; 
    return (os); 
} 

和我用EIGEN_ALIGN_16在我的标头中定义结构为内存对齐。为什么EIGEN_ALIGN_16是一个重复的符号,如果一个头卫兵应该防止多重包含?谢谢你的澄清。

+2

除了很好的答案,你的'endif'应该在头文件的末尾,否则它是无用的。 – Phil1970

+0

“标题”文件通常只有声明(类型和名称,也称为接口)。这些定义(所有的实现细节)通常进入实现文件,后缀为.c或.cpp。 –

回答

3

标头防护可防止在单个编译单元(.o文件)中多次包含这些符号。但是,您已经在头文件中声明了一个实际变量,因此包含此头的每个编译单元都将获得自己的变量副本。在将包含符号的多个目标文件链接在一起之前,这不是问题。这就是为什么问题由ld报告而不是gcc。

更好的方法是将变量声明放入编译单元(.c或.cpp文件之一)中,并在头文件中使用extern来引用该单个实例。

这是一个即使是高级软件开发人员也可能遇到的问题。

3

包含防护可防止在同一个.cpp文件内的多个包含物

但是,您将其包含在多个.cpp文件中。由于该头文件定义了一个对象(EIGEN_ALIGN_16),因此它将包含在两者中,然后链接程序会抱怨有两个重复的定义。

相关问题