cpp在主源文件中包含.cpp文件会导致“重复符号”错误

时间:2018-08-28 16:08:51

标签: c++ header-files software-design

我一直坚持如何将项目分成几个源文件和头文件。我目前的做法似乎笨拙和错误。任何评论表示赞赏!

我有四个文件:

  • main.cpp是主程序。它将创建一些树节点,并调用一个遍历它们的函数。
  • TreeNode.h是头文件,我在其中声明了一个简单的类TreeNode
  • TreeNode.cpp是我定义类TreeNode
  • 的构造函数的地方
  • utils.cpp是我在TreeNode上定义一些功能的地方,例如打印树。

问题是,我应该include TreeNode.h文件在哪里?

  • 如果我同时将其包含在main.cpputils.cpp中(由于它们都使用TreeNode类,则编译器会给我一个“重复符号”错误。这可能是因为我包含了utils.cpp中的main.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`
  • 如果我仅在TreeNode.h文件中包含main.cpp,则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;
}

2 个答案:

答案 0 :(得分:2)

如编译器输出所示,您正在同时编译main.cpputils.cpp。您的main.cpp包含utils.cpp,因此您在其中定义的函数会被编译两次,因此符号重复。

根据经验,切勿包含.cpp文件。将#include视为将一个文件的内容实际包含到另一个文件中。我想您已经尝试解决无法使用utils.cppmail.cpp中的内容的问题。为了解决TreeNode.h中的这个添加函数 declarations (就像一个函数的签名,例如int foo(double);,同时在{{1}中保留它们的 definition }(例如utils.cpp

答案 1 :(得分:0)

您可以使用包括防护。例如:

#ifndef TREENODE_H
#define TREENODE_H

class TreeNode 
{
    // stuff
};

#endif /* TREENODE_H */

请注意,每个头文件的保护名称(在这种情况下为TREENODE_H)必须是唯一的。是的,它可以随您想要。

问题编辑后进行了编辑:

不包括utils.cpp。实际上,切勿包含*.cpp :)将其更改为#include "utils.h"。这就是导致该链接器错误的原因。

相关问题