【问题标题】:cpp include .cpp files in main source file causes "duplicate symbol" error [duplicate]cpp 在主源文件中包含 .cpp 文件导致“重复符号”错误[重复]
【发布时间】:2022-12-03 16:50:35
【问题描述】:

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

我有四个文件:

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

问题是,我应该把includeTreeNode.h文件放在哪里?

  • 如果我将它同时包含在main.cpputils.cpp 中(因为它们都使用TreeNode 类,我的编译器会给我一个“重复符号”错误。这可能是因为我在@987654334 中包含了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.hutils.cpp 文件将不会编译。它给出了一个错误error: unknown type name 'TreeNode'

编辑:

下面是四个文件:

主.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;
}

树节点.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

树节点.cpp

#include "TreeNode.h"

TreeNode::TreeNode(int x) {
    val = x;
    left = nullptr;
    right = nullptr;
}

实用程序.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;
}

【问题讨论】:

  • 你用过头球后卫吗?您不在另一个文件中包含 cpp 文件。您为其创建另一个头文件。
  • @MichaelSurette 不,我以前没听说过。但谢谢你给我介绍它!
  • 您应该在任何需要它的源文件中包含 TreeNode.h 文件。您还应该将其包含在这个问题中,因为它是您遇到的问题的核心。
  • 你能至少提供每个文件的包含部分吗?
  • @PeteBecker 感谢您提供检查。现在发布。

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


【解决方案1】:

如您的编译器输出所示,您正在编译 main.cpputils.cpp。你的main.cpp包括utils.cpp所以你在那里定义的函数被编译了两次因此重复的符号。

根据经验,永远不要包含 .cpp 文件。将 #include 视为将一个文件的内容直接包含到另一个文件中。我想你试图解决无法在 mail.cpp 中使用来自 utils.cpp 的东西的问题。为了解决这个添加功能声明TreeNode.h(就像一个函数的签名,例如int foo(double);,同时保持他们的定义utils.cpp(例如int foo(double) { return 0; }

【讨论】:

    【解决方案2】:

    您可以使用包含守卫。例如:

    #ifndef TREENODE_H
    #define TREENODE_H
    
    class TreeNode 
    {
        // stuff
    };
    
    #endif /* TREENODE_H */
    

    请注意,每个头文件的保护名称(在本例中为TREENODE_H)必须是唯一的。是的,它可以是任何你想要的。

    问题编辑后编辑:

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

    【讨论】:

    • 虽然这是个好建议,但它没有解决链接器错误。
    猜你喜欢
    • 1970-01-01
    • 2021-12-26
    • 2020-07-05
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多