0

I have the below main() function call in Hello.cpp

#include "HelloWorld.cpp"

int main(){
HelloWorld helloWorld;
helloWorld.printHelloWorld();
return 0;
}

The other c++ , file which is included has the below code.

#include <iostream>
#include <string>

class HelloWorld{
        public:
        void printHelloWorld();
};

void HelloWorld::printHelloWorld() {
    std::cout << "This is the world" << std::endl;
}

When I execute with Xcode , I see duplicate symbols for printHelloWorld.

duplicate symbol 'HelloWorld::printHelloWorld()' in: Hello.o HelloWorld.o

ld: 1 duplicate symbol for architecture x86_64

How can I fix the above issue?

NNikN
  • 3,720
  • 6
  • 44
  • 86
  • You are compiling `HelloWord.cpp` twice; once when `#include`ing it, the other when you compile it. You can only do one. – cigien Apr 16 '20 at 16:30
  • You should not be `#include`ing .cpp files. Put the class definition in a header, and include that in both your source files. ([Books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) usually mention how to structure things.) – molbdnilo Apr 16 '20 at 16:32
  • Header files are were you can put declarations that can be used by multiple translation units. Source files are where definitions go. C++ itself doesn't make any distinction between the two, that's just a C Preprocessor facility that developers use to organize their code and not repeat themselves, which is why `#include "HelloWorld.cpp"` isn't detected as an error at compile time. – Eljay Apr 16 '20 at 16:35
  • @cigien thanks for pointing that compilation issue, I am trying to understand how will the compilation work if I include the declaration in a different file as mentioned by others versus the one I have mentioned in the my question. If any one can throw some light on it , that would be great. – NNikN Apr 16 '20 at 16:38

1 Answers1

2

You have your file structure wrong.

Non-defining declarations belong in a header file (.h or .hpp ending by convention):

// HelloWorld.h

// No standard library headers required, because you don't use anything from `std::`

class HelloWorld{
    public:
    void printHelloWorld();
};

(Non-inline) definitions belong in a source file (.cpp or .cxx or .cc by convention):

// HelloWorld.cpp

#include "HelloWorld.h"

#include <iostream>
// #include<string> is not needed, since you don't use `std::string` here

void HelloWorld::printHelloWorld() {
    std::cout << "This is the world" << std::endl;
}

and source files should not be included in other files. Only the header files with the declarations should be included:

#include "HelloWorld.h"

int main(){
    HelloWorld helloWorld;
    helloWorld.printHelloWorld();
    return 0;
}

Each source file is by convention compiled as individual translation unit and there may be a definition for a (non-inline) function in only one of the translation units.

#include does essentially nothing more than copy-paste the code from the other file into the files using it. So if you include the .cpp with a definition in another .cpp file, then both translation units for the two .cpp files will contain the definition, violating the one-definition-rule mentioned above.

Your error is telling you that you have the definition for HelloWorld::printHelloWorld() (which is not inline) in two translation units.

walnut
  • 21,629
  • 4
  • 23
  • 59