1

I would like to know what is causing a double definition linker error in my code. It confuses me because there doesn't seem to be any reason for it. I don't think I'm #includeing any .h files in places that would cause this, as my file's #includes are linearly structured.

To be clear, I am not asking what the errors mean, I am asking what, in my code, is causing it. I have already researched on this site (and others) as to what it means, and can't find an answer relevant to what could be causing it in my code.

Btw I am using Visual Studio 2017

Here are the errors:

1>ObjectHandler.cpp

1>Main.cpp

1>Generating Code...

1>ObjectHandler.obj : error LNK2005: "void __cdecl pixelsInit(void)" (?
pixelsInit@@YAXXZ) already defined in Main.obj

1>ObjectHandler.obj : error LNK2005: "void __cdecl pixelsUpdate(void)" (?
pixelsUpdate@@YAXXZ) already defined in Main.obj

1>ObjectHandler.obj : error LNK2005: "void __cdecl spritesInit(void)" (?
spritesInit@@YAXXZ) already defined in Main.obj

1>ObjectHandler.obj : error LNK2005: "void __cdecl spritesUpdate(void)" (?
spritesUpdate@@YAXXZ) already defined in Main.obj

1>ObjectHandler.obj : error LNK2005: "class std::vector<struct pixel,class 
std::allocator<struct pixel> > pixels" (?pixels@@3V?$vector@Upixel@@V?
$allocator@Upixel@@@std@@@std@@A) already defined in Main.obj

1>ObjectHandler.obj : error LNK2005: "class std::map<class 
std::basic_string<char,struct std::char_traits<char>,class 
std::allocator<char> >,struct sprite,struct std::less<class 
std::basic_string<char,struct std::char_traits<char>,class 
std::allocator<char> > >,class std::allocator<struct std::pair<class 
std::basic_string<char,struct std::char_traits<char>,class 
std::allocator<char> > const ,struct sprite> > > sprites" (?sprites@@3V?
$map@V?$basic_string@DU?$char_traits@D@std@@V?
$allocator@D@2@@std@@Usprite@@U?$less@V?$basic_string@DU?
$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?
$basic_string@DU?$char_traits@D@std@@V?
$allocator@D@2@@std@@Usprite@@@std@@@2@@std@@A) already defined in Main.obj

1>fatal error LNK1169: one or more multiply defined symbols found

Here is my code structure:

SimpleTypes.h:

#pragma once

struct loc {

    int x;
    int y;
    int d;
    int s;

};

struct color {

    _int8 r;
    _int8 g;
    _int8 b;
    _int8 a;

};

ComplexTypes.h:

#pragma once
#include "SimpleTypes.h"
#include <string>

struct pixel {

    loc pos;

    color col;

};

struct sprite {

    std::string name;

    std::string file;

    loc pos;

};

ObjectHandler.cpp:

#include "ComplexTypes.h"
#include <string>
#include <map>
#include <vector>

std::vector<pixel> pixels;
std::map<std::string, sprite> sprites;

void pixelsInit(){};

void spritesInit(){};

void pixelsUpdate(){};

void spritesUpdate(){};

Main.cpp

#include "ObjectHandler.cpp"

int main() {

    pixelsInit();
    spritesInit();

    while (true) {

        pixelsUpdate();
        spritesUpdate();

    };

    return 0;
}

1 Answers1

3

In your project you are compiling ObjectHandler.cpp as an independent translation unit. And at the same time you also including ObjectHandler.cpp into Main.cpp where it gets compiled again as part of Main.cpp.

Thus, everything defined in ObjectHandler.cpp gets defined twice in your program. Hence the errors.

The question is: why are you including ObjectHandler.cpp into Main.cpp? What did you try to achieve by that?

And if you, for some unorthodox reason, really want/have to include ObjectHandler.cpp into Main.cpp and compile it as part of Main.cpp, then stop compiling ObjectHandler.cpp as an independent translation unit at the same time.

Meanwhile, a more traditional approach in this case would be to write a proper ObjectHandler.h file for your ObjectHandler.cpp. Something like

#pragma once
#include "ComplexTypes.h"
#include <string>
#include <map>
#include <vector>

extern std::vector<pixel> pixels;
extern std::map<std::string, sprite> sprites;

void pixelsInit();
void spritesInit();
void pixelsUpdate();
void spritesUpdate();

and include it into Main.cpp instead.

Your ObjectHandler.cpp might look as follows

#include "ObjectHandler.h"

std::vector<pixel> pixels;
std::map<std::string, sprite> sprites;

void pixelsInit(){}
void spritesInit(){}
void pixelsUpdate(){}
void spritesUpdate(){}

Note the important detail: the .h file contains declarations only (functions have no bodies and objects are declared with extern), while .cpp file contains definitions (functions have bodies and objects are declared without extern)

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • That makes sense, what should I do instead? How do I go about fixing this? –  Jan 07 '18 at 01:51
  • @PlatinumFrog: It's really a matter of what you *want* to do. The "simplest" solution is: keep including `ObjectHandler.cpp` into `Main.cpp` but *remove* `ObjectHandler.cpp` from the list of Source files in your project, to make sure it does not get compiled independently. – AnT stands with Russia Jan 07 '18 at 01:53
  • However, including a `.cpp` file is a strange thing to do. A normal way to go about it would be: write an additional `ObjectHandler.h` file that only contains *declarations* (not definitions) of what you have in `ObjectHandler.cpp`. Include `ObjectHandler.h` into `Main.cpp` instead of `ObjectHandler.cpp`. Keep `ObjectHandler.cpp` in the project as an independent source file. – AnT stands with Russia Jan 07 '18 at 01:55
  • It is up to you do figure out what you want to do. The question is, again: why did you `#include` `ObjectHandler.cpp` into `Main.cpp`? If this was random, then just stop doing this and follow the second approach: write a proper `ObjectHandler.h` and include it instead. – AnT stands with Russia Jan 07 '18 at 01:56
  • Main.cpp is supposed to handle the graphics rendering, and input. ObjectHandler.cpp is supposed to handle object logic and ai. They both need to take to each other. –  Jan 07 '18 at 02:00
  • I also low-key don't really know what I'm doing honestly. I have lots of experience with other languages, but only a little with this one. This project is a learning experience for me. –  Jan 07 '18 at 02:03
  • @PlatinumFrog: Well, in that case the bottom line is: you are not supposed to `#include` `.cpp` files into each other. `.h` files are for `#inclde`-ing, `.cpp` files are not. Don't `#include` `.cpp` files. If you want your `Main.cpp` to "talk" to `ObjectHandler.cpp` - write a proper header file `ObjectHandler.h` (see above) – AnT stands with Russia Jan 07 '18 at 02:04
  • (I added a sample `ObjectHandler.h` to the answer) – AnT stands with Russia Jan 07 '18 at 02:07