【发布时间】:2018-02-20 15:26:00
【问题描述】:
我有一个main方法,
main.cpp:
#include "MyStruct.h"
MyStruct.h:
#ifndef MYPROJ_MYSTRUCT_H
#define MYPROJ_MYSTRUCT_H
#include <vector>
#include <unordered_map>
bool function1(std::vector<std::string> label){
// actual implementation
}
bool function2(...){ ... }
struct MyStruct{ ... }
#endif
这编译。但是,当我添加 cpp 文件以包含函数定义时,
main.cpp:
#include "MyStruct.h"
MyStruct.h:
#ifndef MYPROJ_MYSTRUCT_H
#define MYPROJ_MYSTRUCT_H
#include <vector>
bool function1(...){ ... }
bool function2(...){ ... }
struct MyStruct{ ... }
#endif
MyStruct.cpp:
#include "MyStruct.h"
// and that's it
仅仅通过包含头文件,我就会得到链接器错误,就好像我多次导入头文件一样;
这里是 CMakeLists:
cmake_minimum_required(VERSION 3.8)
set(CMAKE_CXX_STANDARD 17)
set(SOURCE_FILES main.cpp MyStruct.cpp)
add_executable(my_proj ${SOURCE_FILES})
错误包括所有重复的符号错误。我不知道如何让它工作,因为这是我一直在使用 make 和 g++ 而没有遇到问题的事情;当我在 Cygwin/Windows 上使用 CMake 和 g++ 时,我似乎也没有这个问题(这是在 MacOSX 上)。
接下来,当我将所有函数转换为 .cpp 文件,并且只有声明出现在标头中时,我消除了大多数重复符号,除了:
duplicate symbol __Z8get_uvidv in:
CMakeFiles/main.cpp.o
CMakeFiles/MyStruct.cpp.o
duplicate symbol _uvid in:
CMakeFiles/main.cpp.o
CMakeFiles/MyStruct.cpp.o
ld: 2 duplicate symbols for architecture x86_64
更新源
// header: MyStruct.h
#ifndef MYPROJ_MYSTRUCT_H
#define MYPROJ_MYSTRUCT_H
#include <unordered_map>
#include <vector>
#include "AnotherStruct.h"
bool add_item(std::pair<std::string,float> & item);
void insert_item(std::vector<AnotherStruct> & A, std::pair<std::string,float> element);
...
struct MyStruct {
std::unordered_map<std::string,int> labels;
std::vector<AnotherStruct> data;
MyStruct(std::vector<char *> inputs);
void GetData();
void SortData(bool (*compare)(AnotherStruct &,AnotherStruct &);
//...
}
#endif
还有.cpp:
#include "MyStruct.h"
// implement everything declared in .h
bool add_item(...){
...
}
bool insert_item(...){
...
}
MyStruct::MyStruct(...){
...
}
void MyStruct::GetData(...){
...
}
void MyStruct::SortData(...){
...
}
还有主要的:
#include "MyStruct.h"
错误:
duplicate symbol __Z8get_uvidv in:
main.cpp.o
MyStruct.cpp.o
duplicate symbol _uvid in:
main.cpp.o
MyStruct.cpp.o
我不知道__Z8get_uvidv 可能是什么,_uvid 也可能是什么,所以我认为std imports 或在编译器的底层发生了一些事情.
请记住,当我将所有内容复制到 main 方法或将所有定义保留在头文件中时,所有内容都会编译,我很难过。
【问题讨论】:
-
This answewr 回答了这个问题,但我不喜欢将 Q 用作欺骗目标。
-
那些大括号让我觉得你的标题包含实际的函数定义而不仅仅是前向声明,这也与重复符号一致。
-
@bordeo 你的头文件不应该包含任何函数定义(例如
int f() { return 1; })只有前向声明(例如int f();)除非那些是模板函数或者它们被标记为内联(在这种情况下你应该'不要在别处写他们的定义)。否则,当您在两个不同的文件中包含标头时,在不同的翻译单元(= cpp 文件,如果您愿意的话)中将有相同函数的两个定义,这会使链接器感到困惑。 -
哦,顺便说一句,一个有趣的细节是在类范围内定义的函数被隐式标记为内联。因此,如果您在标头中有
struct C { int method() { return 1; } };,包括它两次不会导致链接器出现问题(method在此处被隐式标记为内联)。但是,您在标题中遇到struct C { int method(); }; int C::method() { return 1; }的问题(假设它被包含两次),第二部分可能应该移动到一个 cpp 文件中。 -
您包含的
AnotherStruct.h,是您编写的还是来自某个第三方库?您是否确保它也不包含定义? (对于您直接或间接包含在AnotherStruct.h中的任何其他标题也是如此)
标签: c++ compiler-errors compilation cmake