Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
230 views
in Technique[技术] by (71.8m points)

c++ - cpp include .cpp files in main source file causes "duplicate symbol" error

I am stuck at how to separate a project into few source files and header files. My current practice seems to be clumsy and mistaken. Any comment is appreciated!

I have four files:

  • main.cpp is the main program. It will create a few tree nodes, and call a function to traverse them.
  • TreeNode.h is the header file where I declare a simple class TreeNode
  • TreeNode.cpp is where I define a constructor of the class TreeNode
  • utils.cpp is where I define a few functions on TreeNode, like printing out the tree.

The question is, where should I include the TreeNode.h file?

  • If I include it both in main.cpp and utils.cpp (since they both use the TreeNode class, my compiler gives me a "duplicate symbol" error. This might be because I included utils.cpp in main.cpp as well.

Like this :

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`
  • If I only include TreeNode.h in main.cpp file, the utils.cpp file will not compile. It gives an error error: unknown type name 'TreeNode'

Edit:

Here are the four files:

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;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

as your compiler output shows, you're compiling both main.cpp and utils.cpp. Your main.cpp includes utils.cpp so functions you defined there are compiled twice hence duplicate symbols.

As the rule of thumb, never include .cpp files. Consider #include as literal inclusion of content of one file into another file. I suppose you tried to resolve the issue that you couldn't use stuff from utils.cpp in mail.cpp. To solve this add function declarations in TreeNode.h (like just a signature of a function, e.g. int foo(double); while keeping their definition in utils.cpp (e.g. int foo(double) { return 0; })


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...