How to use header guards?

Hello

I have a header called Constants.h. I want to use it in main.cpp, Ball.cpp and Paddle.cpp. So I added this to Constants.h: #pragma once since I read somewhere that it is supported in MinGW(for versions later than 3). But that's not working. And how do I use header guards to do the same?

So how do I use it to include a single file multiple times?

Thanks
closed account (S6k9GNh0)
How do you know it's not working?

Wait, what are you trying to accomplish exactly?
Last edited on
Cause I get the following error:

obj\Debug\main.o ||

In function `ZSt7forwardIRKN2sf6VertexEEOT_RNSt16remove_referenceIS4_E4typeE':

c:\mingw\bin\..\lib\gcc\mingw32\4.7.2\include\c++\mingw32\bits\gthr-default.h|403|multiple definition of `BallSpeed'|

obj\Debug\Ball.o:D:\CodeBlocks\SFML 2.0\Games\Pong_Final\Ball.cpp|7|first defined here|
Last edited on
closed account (S6k9GNh0)
I knew it... show the code!
Why not just use the typical means of doing it?

http://en.wikipedia.org/wiki/Include_guard
closed account (S6k9GNh0)
There's actually a few good reasons.

http://en.wikipedia.org/wiki/Pragma_once

I use #pragma once myself and just claim any compiler that doesn't allow it isn't supported.
Last edited on
My codes are quite long, so I am posting only what's relevant.
Here's my Constants.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/****************
*  Constants.h  *
****************/

#ifndef CONSTANTS_H_INCLUDED
#define CONSTANTS_H_INCLUDED


/** Window related constants **/
const int WINDOW_WIDTH = 800;           // specify window width
const int WINDOW_HEIGHT = 600;          // specify window height
const int WINDOW_BPP = 32;              // specify window bits per pixel
const char *WINDOW_CAPTION = "Pong";    // specify window caption


/** Ball related constants **/
sf::Vector2<float> BallSpeed(0.4, 0.4);


#endif // CONSTANTS_H_INCLUDED 


Here's Ball.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include "Ball.h"
#include "Constants.h"

Ball::Ball()
{
    //ctor
}

Ball::Ball(float RADIUS, sf::Color COLOR, const char *BUFFER_NAME)
{
    ballObject.setRadius(RADIUS);
    ballObject.setFillColor(COLOR);

    paddleHit.loadFromFile(BUFFER_NAME);
    Sound_PaddleHit.setBuffer(paddleHit);
}

void Ball::Init(sf::Vector2f POSITION)
{
    ballObject.setPosition(POSITION);
    currentSpeed = BallSpeed;
}

void Ball::deflectX()
{
    currentSpeed.x = -currentSpeed.x;
}

void Ball::deflectY()
{
    currentSpeed.y = -currentSpeed.y;
}

void Ball::accelerate(Paddle PLAYER)
{
    currentSpeed.y = (ballObject.getGlobalBounds().top
                        + ballObject.getGlobalBounds().height / 2
                            - PLAYER.getRect().top
                                - PLAYER.getRect().height / 2) / 100;
}

void Ball::stopMoving()
{
    currentSpeed = sf::Vector2<float>(0.0f, 0.0f);
}
void Ball::resetSpeed()
{
    currentSpeed = BallSpeed;
}

void Ball::playHitSound()
{
    Sound_PaddleHit.play();
}

bool Ball::isColliding(sf::RectangleShape RECTANGLE)
{
    if(ballObject.getGlobalBounds().intersects(RECTANGLE.getGlobalBounds()))
        return true;
    return false;
}

bool Ball::isColliding(sf::FloatRect RECT)
{
    if(ballObject.getGlobalBounds().intersects(RECT))
        return true;
    return false;
}

sf::Vector2f Ball::getBallPosition()
{
    return ballObject.getPosition();
}

float Ball::getBallRadius()
{
    return ballObject.getRadius();
}

void Ball::move()
{
    ballObject.move(currentSpeed.x, currentSpeed.y);
}

void Ball::update(sf::RenderWindow &WINDOW)
{
    WINDOW.draw(ballObject);
}

Ball::~Ball()
{
    //dtor
}


And here's a part of main.cpp:
1
2
#include "Ball.h"
#include "Constants.h" 


But still I am getting the same error(already mentioned in one of the above posts, number three to be precise).
Last edited on
Both traditional header guards and #pragma once accomplish the same thing, which is to prevent including the same declarations multiple times in the same module.

However, neither will protect you from including the same definitions in multiple modules, which is what you've done.

Lines 10-17 in constants.h are defining variables. Therefore, if you include constants.h in multiple modules, you will have multiple definitions of these variables at link time, which is what the linker is complining about.

You should never define variables in a header file.
What you should do is declare the variables in the header.

In constants.h:
1
2
3
#pragma once 
extern const int WINDOW_WIDTH; 
.. etc 


Then in one and only one of your .cpp files:
1
2
 
const int WINDOW_WIDTH = 800;           // specify window width 

Last edited on
In C++ consts have internal linkage by default, so it's OK to have then defined in the header. In fact, this style makes it easier for the compiler to inline the value than when you declare then with extern in the header and then define them in a source file.

(If you're sharing the header with C code, then what you need to add the static keyword to all the consts. You can use the static keyword with C++, but it's not needed.)

So, these are fine

1
2
3
const int WINDOW_WIDTH = 800;           // specify window width
const int WINDOW_HEIGHT = 600;          // specify window height
const int WINDOW_BPP = 32;              // specify window bits per pixel 


But const char * isn't const: it's a non-const pointer (to a const string). If you want it to be totally const then you need to make the pointer const, too.

char const * const WINDOW_CAPTION = "Pong";

now it's actually a const (and has internal linkage like the int consts)

And if you make BallSpeed const as well, then you don't need to use extern, etc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/****************
*  Constants.h  *
****************/

#ifndef CONSTANTS_H_INCLUDED
#define CONSTANTS_H_INCLUDED


/** Window related constants **/
const int WINDOW_WIDTH = 800;           // specify window width
const int WINDOW_HEIGHT = 600;          // specify window height
const int WINDOW_BPP = 32;              // specify window bits per pixel
char const * const WINDOW_CAPTION = "Pong";    // specify window caption (now really const)


/** Ball related constants **/
const sf::Vector2<float> BallSpeed(0.4, 0.4); // it is supposed to be a constant?


#endif // CONSTANTS_H_INCLUDED  


Andy
Last edited on
@Andy


Thanks, now it works. So, I'd have to define everything(variables etc.) as constants to use it the way I am using? And is their any alternative to declaring everything as constants?

Thanks
is their any alternative to declaring everything as constants?

You can declare variables with external linkage.

In someheader.h
1
2
 
extern sf::Vector2<float> SomeVector;  // declaration visible to all modules that include someheader.h 


In one and only one .cpp file, define the vector.
1
2
3
4
 
#include "someheader.h"
...
sf::Vector2<float> SomeVector;  // Can be initialized here if needed  


This makes SomeVector global across all modules that include someheader.h which is a generally a poor practive, but sometimes it is appropriate.

Thanks to Andy for the clarification on internal linkage of consts.


Topic archived. No new replies allowed.