2016-08-20 3 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), он будет включен в оба, и тогда компоновщик будет жаловаться, что существует два дублирующих определения.

Смежные вопросы