2

I have a base class, which is declared in the following header file:

#pragma once
#include "StateHandler.hpp"

namespace ta {
    class GameState {
    public:
        // ...
    };
} /* ta */

Then, I have two children, which look like this:

#pragma once
#include "../GameState.hpp"

namespace ta {
    class DefaultState: public ta::GameState {
    public:
        // ...
    };
} /* ta */

and

#pragma once
#include "../GameState.hpp"

namespace ta {
    class WorldMapState: public ta::GameState {
    public:
        // ...
    };
} /* ta */

When trying to compile that, I get errors, that GameState was not declared in the second of the two children I include. When I remove the #pragma once from the GameState.hpp, it says that GameSate gets redefined. I get why that happens, but I can't find a way to fix that.

UPDATE: Using include-guards doesn't work either. I get the following error, when using #pragma once or include-guards:

In file included from /[...]/include/statemachine/gamestates.hpp:2,
                 from /[...]/include/common.hpp:4,
                 from /[...]/include/statemachine/gamestates/../StateHandler.hpp:5,
                 from /[...]/include/statemachine/gamestates/../GameState.hpp:4,
                 from /[...]/include/statemachine/gamestates/DefaultState.hpp:4,
                 from /[...]/include/statemachine/gamestates.hpp:1,
                 from /[...]/include/common.hpp:4,
                 from /[...]/source/main.cpp:1:
/[...]/include/statemachine/gamestates/WorldMapState.hpp:7:47: error: expected class-name before '{' token
     class WorldMapState: public ta::GameState {
                                               ^

And this is the error I get, when I don't use include-guards or #pragma once in the GameState.hpp (this error appears 3 times):

In file included from /[...]/include/common.hpp:5,
                 from /[...]/source/main.cpp:1:
/[...]/include/statemachine/GameState.hpp:4:11: error: redefinition of 'class ta::GameState'
     class GameState {
           ^~~~~~~~~
In file included from /[...]/include/statemachine/gamestates/WorldMapState.hpp:4,
                 from /[...]/include/statemachine/gamestates.hpp:2,
                 from /[...]/include/common.hpp:4,
                 from /[...]/include/statemachine/gamestates/../StateHandler.hpp:5,
                 from /[...]/include/statemachine/gamestates/../GameState.hpp:1,
                 from /[...]/include/statemachine/gamestates/DefaultState.hpp:4,
                 from /[...]/include/statemachine/gamestates.hpp:1,
                 from /[...]/include/common.hpp:4,
                 from /[...]/source/main.cpp:1:
/[...]/include/statemachine/gamestates/../GameState.hpp:4:11: note: previous definition of 'class ta::GameState'
     class GameState {
StuntHacks
  • 457
  • 3
  • 15
  • 1
    Have you tried `ifndef` instead of `pragma`? I remember, that an old (ancient) gcc had a bug regarding `pragma once`. Which compiler version are you using? – hellow Oct 08 '18 at 11:43
  • Can you please edit your question to include the *exact* errors (copy-pasted as text, in full and complete)? – Some programmer dude Oct 08 '18 at 11:46
  • 1
    1) I never use `pragma once`. It tends to have buggy implementations which can take an age to diagnose. 2) drop the `ta::` from your inheritance. What you have is perfectly legal though. – Bathsheba Oct 08 '18 at 11:47
  • @mch This answer is outdated because it report about experiments performed on 20 year old compilers. An updated answer could be great because include guards are error prone too. (And have maintenance cost) – Oliv Oct 08 '18 at 12:03
  • 1
    Not sure if this is "best practices" or just my own pet peeve (from experience), but path traversal like `#include "../GameState.hpp"` is bad for larger projects. Instead use `#include "GameState.hpp"` and specify the include header location using `-Iblahblah` on your compile line. – Eljay Oct 08 '18 at 12:15
  • @hellow Using `ifndef` doesn't work either. – StuntHacks Oct 08 '18 at 15:28
  • @Someprogrammerdude I updated the answer. – StuntHacks Oct 08 '18 at 15:28
  • It seems to me that you have a circular dependency for your header files. You need to break it somehow, if possible using *forward declarations*. – Some programmer dude Oct 08 '18 at 15:33
  • 1
    @Someprogrammerdude Yes, that was it. I thought of that as well, but I couldn't find any. Your comment made me look again and I accidently included the `common.hpp`-file in the `GameState.hpp`. If you post it as an answer, I can accept it as correct. – StuntHacks Oct 08 '18 at 15:37

2 Answers2

2

According to this answer #pragma once has unfixable bugs. It should never be used.
You can use header guards like below

#ifndef HEADER_H
#define HEADER_H

// Header file code

#endif
Mayur
  • 2,583
  • 16
  • 28
0

#pragma once is not a standard even it's supported by many compilers should not used to guard header files instead use #ifndef. As there is no standard behavior for #pragma once, you shouldn't assume that the behavior will be the same on all compiler.

Sanjeev
  • 348
  • 2
  • 9