cpp 在主源文件中包含 .cpp 文件导致 "duplicate symbol" 错误
cpp include .cpp files in main source file causes "duplicate symbol" error
我对如何将一个项目分成几个源文件和头文件感到困惑。我目前的做法似乎是笨拙和错误的。欢迎任何评论!
我有四个文件:
main.cpp
是主程序。它会创建一些树节点,并调用一个函数来遍历它们。
TreeNode.h
是头文件,我在其中声明了一个简单的 class TreeNode
TreeNode.cpp
是我定义 class TreeNode
的构造函数的地方
utils.cpp
是我在 TreeNode
上定义一些函数的地方,比如打印树。
问题是,include
TreeNode.h
文件应该放在哪里?
- 如果我将它同时包含在
main.cpp
和 utils.cpp
中(因为它们都使用 TreeNode
class,我的编译器会给我一个 "duplicate symbol" 错误. 这可能是因为我在 main.cpp
中也包含了 utils.cpp
。
像这样:
Scanning dependencies of target main
[ 25%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[ 50%] Building CXX object CMakeFiles/main.dir/utils.cpp.o
[ 75%] Linking CXX executable main
duplicate symbol __Z13inorder_printP8TreeNode in:
CMakeFiles/main.dir/main.cpp.o
CMakeFiles/main.dir/utils.cpp.o
duplicate symbol __Z16inorderTraversalP8TreeNode in:
CMakeFiles/main.dir/main.cpp.o
CMakeFiles/main.dir/utils.cpp.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [main] Error 1
make[2]: *** [CMakeFiles/main.dir/all] Error 2
make[1]: *** [CMakeFiles/main.dir/rule] Error 2
make: *** [main] Error 2`
- 如果我只在
main.cpp
文件中包含 TreeNode.h
,utils.cpp
文件将不会编译。它给出了一个错误 error: unknown type name 'TreeNode'
编辑:
这是四个文件:
main.cpp
#include <iostream>
#include <vector>
#include "TreeNode.h"
#include "utils.cpp"
using namespace std;
int main() {
TreeNode * root = new TreeNode(0);
root->right = new TreeNode(2);
root->right->right = new TreeNode(3);
// inorder_print(root);
std::vector<int> v = inorderTraversal(root);
// print out vector
for (auto i = v.begin(); i != v.end(); ++i){
std::cout << *i << ' ';
}
std::cout << std::endl;
return 0;
}
TreeNode.h
#ifndef TREE_TREE_H
#define TREE_TREE_H
class TreeNode{
public:
int val;
TreeNode * left;
TreeNode * right;
TreeNode(int x);
};
#endif //TREE_TREE_H
TreeNode.cpp
#include "TreeNode.h"
TreeNode::TreeNode(int x) {
val = x;
left = nullptr;
right = nullptr;
}
utils.cpp
#include <vector>
#include <iostream>
// #include "TreeNode.h"
// tested correct
void inorder_print(TreeNode * root){
// print out the tree content in inorder traversal
while(root != nullptr){
std::cout << root->val << std::endl;
inorder_print(root->left);
inorder_print(root->right);
break;
}
}
std::vector<int> inorderTraversal(TreeNode * root){
std::vector<int> v;
while(root != NULL){
v.push_back(root->val);
if (root->left != NULL){
v.insert(v.end(), inorderTraversal(root->left).begin(), inorderTraversal(root->left).end());
break;
}
if (root->right != NULL){
v.insert(v.end(), inorderTraversal(root->right).begin(), inorderTraversal(root->right).end());
break;
}
break;
}
return v;
}
你可以使用 include guards。例如:
#ifndef TREENODE_H
#define TREENODE_H
class TreeNode
{
// stuff
};
#endif /* TREENODE_H */
请注意,每个头文件的保护名称(在本例中为 TREENODE_H
)必须是唯一的。是的,它可以是任何你想要的。
问题编辑后编辑:
不包括 utils.cpp
。事实上,永远不要包含 *.cpp
:) 将其更改为 #include "utils.h"
。这就是导致链接器错误的原因。
如您的编译器输出所示,您正在编译 main.cpp
和 utils.cpp
。你的 main.cpp
包括 utils.cpp
所以你定义的函数被编译了两次因此重复的符号。
根据经验,永远不要包含 .cpp 文件。将 #include
视为将一个文件的内容直接包含到另一个文件中。我想你试图解决无法在 mail.cpp
中使用来自 utils.cpp
的内容的问题。要解决此添加函数 declarations in TreeNode.h
(就像函数的签名,例如 int foo(double);
同时保持其 definition 在 utils.cpp
中(例如 int foo(double) { return 0; }
)
我对如何将一个项目分成几个源文件和头文件感到困惑。我目前的做法似乎是笨拙和错误的。欢迎任何评论!
我有四个文件:
main.cpp
是主程序。它会创建一些树节点,并调用一个函数来遍历它们。TreeNode.h
是头文件,我在其中声明了一个简单的 classTreeNode
TreeNode.cpp
是我定义 classTreeNode
的构造函数的地方
utils.cpp
是我在TreeNode
上定义一些函数的地方,比如打印树。
问题是,include
TreeNode.h
文件应该放在哪里?
- 如果我将它同时包含在
main.cpp
和utils.cpp
中(因为它们都使用TreeNode
class,我的编译器会给我一个 "duplicate symbol" 错误. 这可能是因为我在main.cpp
中也包含了utils.cpp
。
像这样:
Scanning dependencies of target main
[ 25%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[ 50%] Building CXX object CMakeFiles/main.dir/utils.cpp.o
[ 75%] Linking CXX executable main
duplicate symbol __Z13inorder_printP8TreeNode in:
CMakeFiles/main.dir/main.cpp.o
CMakeFiles/main.dir/utils.cpp.o
duplicate symbol __Z16inorderTraversalP8TreeNode in:
CMakeFiles/main.dir/main.cpp.o
CMakeFiles/main.dir/utils.cpp.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [main] Error 1
make[2]: *** [CMakeFiles/main.dir/all] Error 2
make[1]: *** [CMakeFiles/main.dir/rule] Error 2
make: *** [main] Error 2`
- 如果我只在
main.cpp
文件中包含TreeNode.h
,utils.cpp
文件将不会编译。它给出了一个错误error: unknown type name 'TreeNode'
编辑:
这是四个文件:
main.cpp
#include <iostream>
#include <vector>
#include "TreeNode.h"
#include "utils.cpp"
using namespace std;
int main() {
TreeNode * root = new TreeNode(0);
root->right = new TreeNode(2);
root->right->right = new TreeNode(3);
// inorder_print(root);
std::vector<int> v = inorderTraversal(root);
// print out vector
for (auto i = v.begin(); i != v.end(); ++i){
std::cout << *i << ' ';
}
std::cout << std::endl;
return 0;
}
TreeNode.h
#ifndef TREE_TREE_H
#define TREE_TREE_H
class TreeNode{
public:
int val;
TreeNode * left;
TreeNode * right;
TreeNode(int x);
};
#endif //TREE_TREE_H
TreeNode.cpp
#include "TreeNode.h"
TreeNode::TreeNode(int x) {
val = x;
left = nullptr;
right = nullptr;
}
utils.cpp
#include <vector>
#include <iostream>
// #include "TreeNode.h"
// tested correct
void inorder_print(TreeNode * root){
// print out the tree content in inorder traversal
while(root != nullptr){
std::cout << root->val << std::endl;
inorder_print(root->left);
inorder_print(root->right);
break;
}
}
std::vector<int> inorderTraversal(TreeNode * root){
std::vector<int> v;
while(root != NULL){
v.push_back(root->val);
if (root->left != NULL){
v.insert(v.end(), inorderTraversal(root->left).begin(), inorderTraversal(root->left).end());
break;
}
if (root->right != NULL){
v.insert(v.end(), inorderTraversal(root->right).begin(), inorderTraversal(root->right).end());
break;
}
break;
}
return v;
}
你可以使用 include guards。例如:
#ifndef TREENODE_H
#define TREENODE_H
class TreeNode
{
// stuff
};
#endif /* TREENODE_H */
请注意,每个头文件的保护名称(在本例中为 TREENODE_H
)必须是唯一的。是的,它可以是任何你想要的。
问题编辑后编辑:
不包括 utils.cpp
。事实上,永远不要包含 *.cpp
:) 将其更改为 #include "utils.h"
。这就是导致链接器错误的原因。
如您的编译器输出所示,您正在编译 main.cpp
和 utils.cpp
。你的 main.cpp
包括 utils.cpp
所以你定义的函数被编译了两次因此重复的符号。
根据经验,永远不要包含 .cpp 文件。将 #include
视为将一个文件的内容直接包含到另一个文件中。我想你试图解决无法在 mail.cpp
中使用来自 utils.cpp
的内容的问题。要解决此添加函数 declarations in TreeNode.h
(就像函数的签名,例如 int foo(double);
同时保持其 definition 在 utils.cpp
中(例如 int foo(double) { return 0; }
)