Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

header guard conundrum - already defined in .obj problem

Tags:

c++

I have a class (A) which has to include two files, class X and class Y. unfortunately class Y also needs to include class X in it's header file because the constructor takes a pointer to a class X type as an argument.

The potential problem is that there would be a linker error? as class A now has two copies of class X in it, one that it needs to use, and one from class Y. This is the situation where header guards are of no use. My question is - is this purely a structural problem or is there a way around this?

I really would prefer to not include anything in class Y's header file, in case I want to include THAT in anything else, but is it necessary because of the function prototype?

like image 316
Dollarslice Avatar asked Sep 23 '11 11:09

Dollarslice


People also ask

How do I fix my lnk2005?

This error can occur when a header file defines a function that isn't inline . If you include this header file in more than one source file, you get multiple definitions of the function in the executable. To fix this issue, move the member function definitions inside the class.

Which error can be caused by omitting a header guard?

Without a header guard, a code file could end up with multiple (identical) copies of a given type definition, which the compiler will flag as an error.

How do you guard a header file in C++?

Header Guards in C++ are conditional compilation directives that help to avoid errors that arise when the same function or variable is defined more than once by the mistake of a programmer. According to C++, when a function or a variable is defined more than once, it yields an error.

Can you define functions in header file?

No. If you import the same header from two files, you get redefinition of function. However, it's usual if the function is inline. Every file needs it's definition to generate code, so people usually put the definition in header.


2 Answers

If you have the following:

X.h

#ifndef X_H__
#define X_H__

class X
{
public:
    int foo() { return 1; }
};

#endif

Y.h

#ifndef Y_H__
#define Y_H__

#include "X.h"

class Y
{
public:
    Y(X *pX) { myval = pX->foo(); }
    int myval;
};

#endif

something.cpp

#include "X.h"

...

something_else.cpp

#include "Y.h"

...

Then there should be no problem.

However, if X.h instead looks like this:

#ifndef X_H__
#define X_H__

class X
{
public:
    int foo();
};

int X::foo() { return 1; }

#endif

then you will indeed get a linker error when you try to link something.cpp and something_else.cpp. X::foo will have been defined non-inline into two separate translation units.

like image 167
Oliver Charlesworth Avatar answered Nov 15 '22 10:11

Oliver Charlesworth


You can use a declaration in the Y header.

class X;

Since you only use a pointer to X the compiler doesn't need to know it's definition.

like image 32
jtepe Avatar answered Nov 15 '22 09:11

jtepe