Jump to content
  • Advertisement
Sign in to follow this  
tommytwotoes

Header file problems

This topic is 4895 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I had a cool idea for a demo the other day so as usual i set up a C++ project in .NET and started coding. However when i came to compile i came across some strange problems. I've been looking at this code for ages now so you lot are my last hope. Head.cpp #include "vector2.h" #include "head.h" Head::Head(){} Head::~Head(){} void Head::Init(){} Head.h #ifndef _HEAD_H_ #define _HEAD_H_ class Head { public: Head(); ~Head(); void Init(); private: Vector2 mData; }; #endif Vector2.h #ifndef _VECTOR2_H_ #define _VECTOR2_H_ class Vector2 { public: float x, y; Vector2(); }; // Construtors Vector2::Vector2() {} #endif Main.cpp #include "vector2.h" #include "head.h" int main(int argc, char **argv) { Vector2 pos; return 0; } The problem is when i try and compile i get the following error: MyProject error LNK2005: "public: __thiscall Vector2::Vector2(void)" (??0Vector2@@QAE@XZ) already defined in head.obj I know i am doing something stupid but i can't see it. Other programs i have written have had the same layout and they work fine. I'm thinking it might be some .NET option i need to change. cheers

Share this post


Link to post
Share on other sites
Advertisement
You need to either put your Vector2 function definitions in a cpp file or inline them, i.e.:

Vector2.h
#ifndef _VECTOR2_H_
#define _VECTOR2_H_

class Vector2
{

public:

float x, y;
Vector2(){}

};

#endif

Or

Vector2.h
#ifndef _VECTOR2_H_
#define _VECTOR2_H_

class Vector2
{

public:

float x, y;
Vector2();

};

#endif

Vector2.cpp
#include "Vector2.h"

// Construtors
Vector2::Vector2(){}

Although since the constructor is empty unless you plan to add additional constructors or do some work in the default constructor it would be better as:
Vector2.h
#ifndef _VECTOR2_H_
#define _VECTOR2_H_

struct Vector2
{
float x, y;
};

#endif


Enigma

Share this post


Link to post
Share on other sites
You don't have to, you may.

C++ has a rule which says that every symbol you use should be defined once and only once.

Share this post


Link to post
Share on other sites
It helps in situations like this to have a reasonable understanding of how compiling and linking works.

Compiling works on compilation units. You don't compile the whole program as a single unit. You actually compile each source file (.cpp) into an object file (.obj, usually). Any includes throw everything from the included file into the included-in file, and it is treated as a single file. Then, once all these object files are created, the linker goes through and combines them into a single exe (or dll or lib or whatever).

So what happens here is that your compiler tries to compile Head.cpp. It includes vector2.h and head.h. It then compiles all functions that are defined. In this case, one of those functions is the constructor for vector2, so the function gets compiled inot Head.obj.

Then your compiler compiles Main.cpp. Main.cpp includes vector2.h and head.h as well. And since vector2::vector2() is defined in vector2.h, the function gets compiled into Main.obj.

Then your linker tries to link all these different object files. But it gets confused because vector2::vector2() is compiled in two different places, Head.obj and Main.obj.

If you had placed the definition of vector2::vector2() into vector2.cpp, then it would have only gotten compiled when vector2.cpp got compiled into vector2.obj. The other .cpp files would have included vector2.h, just as they currently do, but vector2.h would have only contained a declaration of the function, not the definition itself, and thus the function wouldn't have gotten compiled in any of these other files. And therefore you wouldn't have a problem.

Or if you inlined the function, the compiler would actually want the function to be defined in each .cpp in which it was used, so that it can insert the actual code itself, rather than a mere function call, when compiling.

That's why you need to either put the definition in another .cpp, or make the function inline. Make some sense?

Share this post


Link to post
Share on other sites
Functions marked inline are not subject to linkage outside the current translation unit (current compiling source file).
If you don't inline your functions (member functions defined within a class are implicitly inline) they will be considered defined symbols to be exported for global linkage.
When the linker comes to link your 'head.cpp' and 'main.cpp', it will find the Vector constructor defined in both these object files, and thus complain about redefinition.

Share this post


Link to post
Share on other sites
Quote:
Original post by tommytwotoes
Well shouldn't it work if i don't inline my functions?

If so, why doesn't it?


Because if you don't every source file that includes your header will contain a copy of the function, and the linker cannot figure out which one it is supposed to use in the program, as, for all it knows, each could be different. This is precisely the error message you get.

Share this post


Link to post
Share on other sites
yeah that makes sense. what do the #ifndef, #endif preprocessor directives do then? I thought that stopped the code being compiled twice.

Share this post


Link to post
Share on other sites
Like Agony said, the code isn't compiled as a whole, but in translation units.

Every cpp file is compiled completely independently, so while inclusion guards prevents the same header from being included more than once in a single translation unit, it has no effect across the compilation of different translation units.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!