6

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?

Dollarslice
  • 9,917
  • 22
  • 59
  • 87
  • This shouldn't be a problem, so long as you haven't defined any non-inline functions in your header files. Can you post some representative code? – Oliver Charlesworth Sep 23 '11 at 11:21
  • actually I'm sorry, I think the error was coming from somewhere else. Even so though, this is good to learn. So as long as the header files contain only prototypes, you can include a number of the same one without any problems? – Dollarslice Sep 23 '11 at 11:25
  • 1
    You can have the class definition, along with member-function definitions, so long as they're inlined into the class body itself, e.g.: `class X { int foo() { return 1; } };`. This is not fine: `class X { int foo(); }; int X::foo() { return 1; }`. – Oliver Charlesworth Sep 23 '11 at 11:26
  • just made a minor edit to the question so it's of more use to the community - it's now a theoretical one, but the content's the same. – Dollarslice Sep 23 '11 at 11:27

2 Answers2

11

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.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • 2
    And the workaround...? Noone wants to define methods within a class. – Tomáš Zato Mar 14 '13 at 22:07
  • @TomášZato: The workaround? There are two options; either you define the member function "inline" in the class definition, or you define it in a separate .cpp file. – Oliver Charlesworth Mar 15 '13 at 00:56
  • This just saved me so much time. But I still don't get why this is the case. In my code I had a file X.h without a class, just two helper methods. Now I put them inside a class, made them static and it works. Can anyone explain that? – Verena Haunschmid Sep 02 '15 at 09:47
  • @TomášZato : The problem is not on the method's definition being within a class ( "...a class's declaration within a header." would be more accurate ). The problem is on the method's definition being within a header. :) It must be inline. – Poniros Nov 16 '19 at 02:06
1

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.

jtepe
  • 3,242
  • 2
  • 24
  • 31