views:

1061

answers:

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

server.h needs:
- 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?

+15  A: 

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
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
@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
The underscore identifiers are reserved for the standard libraries, that's why they're allowed to use them.
Daniel Earwicker
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
+9  A: 

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
A: 

@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
This belongs in a comment under the answer in question.
Ryan Fox
True, this could be a comment, but given the "green" nature of the question, this would probably be helpful to the questioner.
Scottie T
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
@lassevk, true. (-:
Rob Wells
+1  A: 

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
+6  A: 

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
Awesome. Too many people try to solve problems without realizing why they exist in the first place.
Tom
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
@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
Daniel - bad naming doesn't cause circular dependencies.
Tom
+2  A: 

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
You're suggesting a compiler-specific optimization to include guards, when the OP's problem has nothing to do with compile time.
Tom
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