5
game.h needs:
- packet.h
- socket.h

socket.h needs:
- game.h

The problem comes when I try to include socket.h into game.h, because socket.h has game.h included already. How do I solve these kind of problems?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96

6 Answers6

17

The usual way, use #ifdef and #define in your header files

inside game.h:

#ifndef GAME_H
#define GAME_H

.. rest of your header file here

#endif

This way, the contents will be read multiple times, but only defined once.

Edit: Removed underscores at start and end of identifier per comments.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • lassevk: Since this is the accepted answer, might as well do The Right Thing: C++ does not like underscores at the beginning of identifiers (even though it's legal, for use in libraries). – Konrad Rudolph Dec 21 '08 at 13:11
  • @Konrad -- I don't think that applies to preprocessor macros. On my Mac the standard C++ header files are filled with just these sorts of definitions. /** @file stack * This is a Standard C++ Library header. */ #ifndef _GLIBCXX_STACK #define _GLIBCXX_STACK 1 – tvanfosson Dec 21 '08 at 14:14
  • The underscore identifiers are reserved for the standard libraries, that's why they're allowed to use them. – Daniel Earwicker Dec 21 '08 at 14:24
  • 1
    Consider also using forward declarations as recommended in other answers. When it is feasible it not only solves your problmem but also will speed compilation time. – David Rodríguez - dribeas Dec 21 '08 at 17:04
9

The key is forward declaration. Take the stuff from game.h that is required in socket.h (or vice-versa) and forward-declare it in yet another header, e.g. game_forwards.h. As an example, consider the following:

// game_fwd.h

#ifndef GAME_FWD_H
#define GAME_FWD_H

class game;

#endif // ndef GAME_FWD_H

// game.h

#ifndef GAME_H
#define GAME_H

#include "socket.h"

class game {
    socket* m_sck;
};

#endif // ndef GAME_H

// socket.h

#ifndef SOCKET_H
#define SOCKET_H

#include "game_fwd.h"

class socket {
    game* m_game;
};

#endif // ndef SOCKET_H

Clearly, for this to work, it's important to separate interface and implementation.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
8

In addition to the techniques (forward definition and read-once headers), you need to work out why your socket header requires anything from the game header, and package your system into modules with a single dependency order. There shouldn't be any reason a socket class needs to know about what game it is being used for.

Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171
  • Awesome. Too many people try to solve problems without realizing why they exist in the first place. – Tom Dec 21 '08 at 16:22
  • It's bad naming. My game class parses incoming packets, socket calls a parse function... sometimes my game class also needs to send packets back, and it needs access to the socket class –  Dec 21 '08 at 17:16
  • 1
    @Daniel: you still have a contorted organization, whatever the names. Reorganize, as Pete Kirkham suggested, so that you can have a clean, non-incestuous set of dependencies. – Jonathan Leffler Dec 21 '08 at 17:53
  • Daniel - bad naming doesn't cause circular dependencies. – Tom Dec 23 '08 at 04:00
3

For completeness, another alternative is:

#pragma once 

at the top of the file.

This has the advantage that the file is not opened repeatedly, saving compile time.

It has the disadvantage of not being standard, so not all compilers support it. Works reliably in Visual C++.

Steve Fallows
  • 6,274
  • 5
  • 47
  • 67
  • You're suggesting a compiler-specific optimization to include guards, when the OP's problem has nothing to do with compile time. – Tom Dec 21 '08 at 16:20
  • I never suggested the OP's problem was about compile time. I was merely trying to point out another *possible* way to deal with include files, since the OP seemed to be fairly new to the issue. I hardly think that rates a down vote but to each his own. :) – Steve Fallows Dec 21 '08 at 16:25
1

There's no elegant way around it that I can think of - your best bet is to forward-define the functions that will actually be used. So, if game.h only uses the connect() function from socket.h, add this line to game.h:

void connect();

And remove the socket.h import. Of course if the signature of connect() changes you'll need to remember to update the forward definition too, so this solution is far from ideal. If you possibly can, modify the design to avoid the circular dependencies.

If game.h just needs to know about a class in socket.h, forward define it like this:

class Socket;

There are some caveats when it comes to inline functions and member objects, see The C++ FAQ Lite.

Jody
  • 116
  • 2
0

@lassevk, shouldn't that be "the header file will be opened several times, but the preprocessor will only read the contents of the file between the #ifndef and #endif once, during the first read. After then the preprocessor will ignore bewteen the PP macros because _GAME_H has been defined."

Rob Wells
  • 36,220
  • 13
  • 81
  • 146
  • This belongs in a comment under the answer in question. – Ryan Fox Dec 21 '08 at 13:10
  • True, this could be a comment, but given the "green" nature of the question, this would probably be helpful to the questioner. – Scottie T Dec 21 '08 at 13:14
  • Well, it depends on what you mean. The contents of the file will of course be read each time the file is included, by the preprocessor, but yes, it will ignore it, but it can't ignore the contents without reading it, since it needs to find the #endif :) – Lasse V. Karlsen Dec 21 '08 at 15:38