Error while using the recursive inclusion of Qt headers [duplicate] - c++

This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 4 years ago.
I have big project in which appeared extremely incomprehensible mistake, after which I created a new project repeated it:
struct of project is simple:
main.cpp
first.h
second.h
first.h
#ifndef FIRST_H
#define FIRST_H
#include "second.h"
class first
{
public:
first();
};
#endif // FIRST_H
second.h
#ifndef SECOND_H
#define SECOND_H
#include "first.h"
class second
{
public:
second();
};
#endif // SECOND_H
Everything is quite logical, but Qt Creator thinks quite differently:
D:\WinFiles\Documents\QT\DELME1\DELME1\second.h:1: error: unterminated conditional directive
I am a bit at a loss case as for inheritance this construction is needed

Problem solving for MinGW compiler:
//first.h
#ifndef FIRST_H
#define FIRST_H
class second;
class first
{
public:
first();
};
#endif // FIRST_H
//second.h
#ifndef SECOND_H
#define SECOND_H
class first;
class second
{
public:
second();
};
#endif // SECOND_H
The second solution is to use MSVC compiller for qt which will guess what needs to be
done by itself and compiled all of the examples correctly.

Related

ifndef with cpp file in new library [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
Hello im trying to build my own library in c++, and after many hours of searching and trying i learnt that a good way of doing one would be using nested classes, so i made some code in this form of tree:
file tree
So i divided all the class files into different header files(i know this is harder and maybe not necessary but i wanted have it like that, if nothing more then just for training). And so to keep the nested class connected, but in different files, each header needs to include its child and or parent to function correctly. This didnt work, gave me errors of recursive include (duh) so i searched online and found #ifndef and #define and i used them in this way:
//A.hpp
#ifndef A_HPP_INCLUDED // some unique macro
#define A_HPP_INCLUDED
class A
{
public:
class B;
class C;
};
#include "B.hpp"
#include "C.hpp"
#endif
//B.hpp
#ifndef B_HPP_INCLUDED
#define B_HPP_INCLUDED
#include "A.hpp"
class A::B
{
public:
static int num;
void func();
};
#endif
int A::B num = 5;
//C.hpp
#ifndef C_HPP_INCLUDED // some unique macro
#define C_HPP_INCLUDED
#include "A.hpp"
class A::C
{
public:
void func();
};
#endif
But the second i add #include "B.hpp" into the B.cpp file it immediately gives me error that all variables and functions ive added in this way are defined multiple times. Without cpp files it works perfectly, but with them it crashes. In fact this happens when adding any cpp file to any header
Answers to this problem are welcome, but if you have any tips on how to make library files in a better way or even just random tips, thatd be awesome!
fyi im using qt creator, qmake, c++11. if qmake file is needed ill send it but i think everything there is good.
The files in question (for reproducing the problem):
//testlibrary.hpp
#ifndef TESTLIBRARY_HPP_INCLUDED // some unique macro
#define TESTLIBRARY_HPP_INCLUDED
class TestLibrary
{
public:
class Core;
class SFML;
};
#include <Core/Core.hpp>
#include <SFML++/SFMLpp.hpp>
#endif
//Core.hpp
#pragma once
#ifndef CORE_HPP_INCLUDED // some unique macro
#define CORE_HPP_INCLUDED
#include <testlibrary.hpp>
class TestLibrary::Core
{
public:
class Constants;
};
#include "Constants.hpp"
#endif
//Constants.hpp
#pragma once
#ifndef CONSTANTS_HPP_INCLUDED // some unique macro
#define CONSTANTS_HPP_INCLUDED
#include "Core.hpp"
class TestLibrary::Core::Constants
{
public:
static float const_PI;
static float const_Euler;
Constants();
};
float TestLibrary::Core::Constants::const_PI = 3.1415;
float TestLibrary::Core::Constants::const_Euler = 2.71828;
#endif
//SFMLpp.hpp
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#ifndef SFML_HPP_INCLUDED // some unique macro
#define SFML_HPP_INCLUDED
#include <testlibrary.hpp>
class TestLibrary::SFML
{
public:
class Text;
};
//#include "Text.hpp"
#endif
//Text.hpp
#pragma once
#ifndef TEXT_HPP_INCLUDED // some unique macro
#define TEXT_HPP_INCLUDED
#include "SFMLpp.hpp"
class TestLibrary::SFML::Text : public sf::Text
{
public:
sf::Font font_;
Text();
Text(std::string string);
Text(std::string string, sf::Font &font);
Text(std::string string, sf::Font &font, int size);
Text(std::string string, sf::Font &font, int size, sf::Color color);
void setTextInt(int inputText);
void drawText(sf::RenderWindow &window);
};
#endif
//text.cpp
#include "text.hpp"
Static variables must be defined only once in the entire program. If you define them in a header file, they are defined in every .cpp file that includes the header.
Move these lines into a .cpp file:
float TestLibrary::Core::Constants::const_PI = 3.1415;
float TestLibrary::Core::Constants::const_Euler = 2.71828;
Or use constexpr to define them in place:
class TestLibrary::Core::Constants
{
public:
static constexpr float const_PI = 3.1415;
static constexpr float const_Euler = 2.71828;
In header files you should have only declarations (except templates but it is not a case here), statements like:
float TestLibrary::Core::Constants::const_PI = 3.1415;
float TestLibrary::Core::Constants::const_Euler = 2.71828;
are definitions and that is why you have error. These statements should be in some c++ file.

C++ Why Is There "Unknown Type" When Class Header is Included? [duplicate]

This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 6 years ago.
I have this header file and I'm trying to make variables of type Item. I've included #include "Item.h" and yet I still get a unknown type name Item error on both private variables when I compile.
#ifndef PLAYER_H
#define PLAYER_H
#include <vector>
#include "Item.h"
using std::vector;
class Player
{
public:
// constructor
Player( void );
// destructor
virtual ~Player( void );
private:
Item item;
std::vector <Item> inventory;
};
#endif /* PLAYER_H */
Whats up with this?
Heres the Item.h that I'm including
#ifndef ITEM_H
#define ITEM_H
#include <string>
#include "Player.h"
#include "GlobalDefs.h"
class Item {
public:
Item();
Item(gold_t v, std::string n);
virtual ~Item();
// Getter
inline virtual gold_t GetValue (void)
{
return value;
}
// Getter
inline virtual std::string GetName (void);
// Getter
virtual std::string GetItemText(void);
protected:
gold_t value;
std::string name;
};
#endif /* ITEM_H */
If you include Item.h from your cpp file, Player.h is included from it. Then, Player.h includes Item.h again, but thanks to the include guard, this does virtually nothing.
Then, in the included Player.h, no Item is declared yet. Therefore, the compiler will emit the error.
Since nothing from Player.h is used in Item.h, remove #include "Player.h" from Item.h.
You're including "Player.h" in "Item.h" and make it circular dependency. Since it's not necessary at all so just remove it.

Creating a class in C++ error

I have a test class, it has nothing in it apart from the bones of a class.
h:
#ifndef TEST_H_
#define TEST_H_
class Test
{
public:
Test();
};
#endif /* TEST_H_ */
cpp
#include "test.h"
Test::Test()
{
}
And then in my main class I have:
Test *test = new Test();
I also include test.h.
I get the error:
Undefined reference to Test::Test()
Can anyone tell me where i'm going wrong?
Figured it out, even after cleaning the project and restarting the IDE it still wouldn't work. I had to manually add in test.h and test.cpp to my config.pri

Cannot find a namespace despite it being RIGHT THERE

I have a namespace defined in one header file and used in another, but it cannot be found. Specifically, a namespace called "players" defined in "players/Players.hpp" and used in a file called "players/Ownable.hpp" cannot be found in a file called "combat/Targetable.hpp"
The errors are
...\source\combat\Targetable.hpp(7): 'players' : is not a class or namespace name
...\source\combat\Targetable.hpp(7): 'Ownable' : base class undefined
Obviously it's some syntax thing I don't understand. I've spent some time simplifying the code so it looks silly, but bear with me.
// source/players/Players.hpp:
#ifndef PLAYERS_HPP
#define PLAYERS_HPP
#include "../Headers.hpp"
namespace players {
class Player{
// this class compiles fine.
// There used to be a "Players.cpp" but it's been simplified away
public:
int getID(){ return 0; }
int getTeam(){ return 0; }
string getName(){ return ""; }
Vec3 getColor(){ return Vec3(0.0,0.0,0.0); }
};
}
#endif
And players/Ownable.hpp, which is in the same folder as Player.hpp and also compiles fine:
// source/players/Ownable.hpp:
#ifndef OWNABLE_HPP
#define OWNABLE_HPP
#include "Players.hpp"
namespace players {
class Ownable;
typedef boost::shared_ptr<Ownable> OwnablePTR;
typedef boost::weak_ptr<Ownable> OwnableWPTR;
class Ownable {
public:
Ownable(){}
Ownable(int playerID) : playerID(playerID){}
bool isAlliedWith(OwnablePTR other){ return false; }
private:
int playerID;
};
}
#endif
Here's where the fun starts. I have a file at "source/combat/Targetable.hpp", which is in a different directory than the other two. However, the file itself seems to include fine:
// source/combat/Targetable.hpp:
#ifndef TARGETABLE_HPP
#define TARGETABLE_HPP
#include "../players/Ownable.hpp"
namespace combat{
class Targetable : public players::Ownable { // ERROR
public:
Targetable(int playerID){}
//Targetable(players::Player player);
virtual Vec2 getPosition(){
return Vec2();
}
virtual Vec2 getVelocity(){
return Vec2();
}
};
}
#endif
I'm really hoping this is some silly syntax thing that I'm missing. I've even tried
using players::Ownable;
but that A) pollutes the files that include this one, and B) doesn't fix anything. Any help?
EDIT: GManNickG got it, it was a circular include in the Headers.hpp file. Thanks!
You have a circular include.
First consider the purpose of include guards:
// a.hpp
#ifndef A_HPP
#define A_HPP
// stuff
#endif
 
// b.hpp
#ifndef B_HPP
#define B_HPP
#include "a.hpp"
// stuff
#endif
 
// c.hpp
#ifndef C_HPP
#define C_HPP
#include "a.hpp"
#include "b.hpp"
// stuff
#endif
 
// x.cpp
#include "c.hpp"
The inclusion of c.hpp will end up include a.hpp twice. The first time, the guards are not defined and everything is okay, and the second time the guards prevent redefinitions. This is what we want.
This does not work when you have a loop, though. (It will prevent it, which is good, but it does "too well" because the guard is defined right after its tested, which means the contents of the header haven't actually yet been processed). Consider this instead:
// a.hpp
#ifndef A_HPP
#define A_HPP
#include "c.hpp"
// stuff
#endif
 
// b.hpp
#ifndef B_HPP
#define B_HPP
#include "a.hpp"
// stuff
#endif
 
// c.hpp
#ifndef C_HPP
#define C_HPP
#include "b.hpp"
// stuff
#endif
 
// x.cpp
#include "c.hpp"
Which is similar to what you have. x.cpp includes c.hpp, which is the first time it's been included so it defines C_HPP. Then c.hpp includes b.hpp, which includes a.hpp. Then a.hpp includes c.hpp and finds that C_HPP has already been defined, so the include does nothing.
Assuming a.hpp still manages to compile (that is, c.hpp isn't actually needed), then a.hpp finishes, then b.hpp finishes, then c.hpp finally actually defines its contents before returning to x.cpp.
The solution is to minimize the amount of headers you include. Use forward declarations, and most of all: do not use 'include everything' headers! These are terrible. And I suspect that's what Headers.hpp is.
How about class Targetable : public ::players::Ownable { . . .?
Note the global namespace qualification :: before players.

How to make classes in NACHOS (C++)

I am trying to implement a player class, so I created two files in my threads folder,
player.cc and player.h
player.h goes like this :
#ifndef PLAYER_H
#define PLAYER_H
#include "utility.h"
class Player()
{
public:
//getPlayerID();
};
#endif
then player.cc goes like
#include "player.h"
class Player()
{
string playerID;
int timeCycle;
}
Then in my main.cc and threadtest.cc , I add in #include player.h and then I start to errors and it fails to compile. I am new to nachos and a little bit unfamiliar with c++, so I am confused as to how to resolve this problem. Nachos does not provide a solution through the compiler either.
When I type gmake, it says two things for errors.
1. parse error before '(' in player.h (referring to Player())
2. * [main.o] Error 1
Let's go through line-by-line:
#ifndef PLAYER_H
#define PLAYER_H
#include "utility.h"
So far so good, you might check if your compiler supports #pragma once, but the macro will work perfectly fine.
class Player()
() aren't allowed in a class name, take them off
{
public:
//getPlayerID();
};
#endif
The rest of the header file is ok. Let's look at the implementation file:
#include "player.h"
Perfect. Putting a class in a header is the best way to make sure you only have one definition used in your whole program.
class Player()
Parentheses aren't allowed, but here you have a bigger problem. You already have a class with that name. Let the header provide the class definition, the implementation file just needs to provide the non-inline member functions (and any helper code).
{
string playerID;
int timeCycle;
}
Here's a complete corrected version:
#if !defined(PLAYER_H)
#define PLAYER_H
#include <string>
#include "utility.h"
class Player
{
std::string player_id;
int time_cycle;
public:
// this is how you make a constructor, the parenthesis belong here, not on the class name
Player(std::string id, int time);
std::string getPlayerId() const;
};
#endif /* !defined(PLAYER_H) */
and implementation file
#include "player.h"
// and this is how you write a non-inline constructor
Player::Player(std::string id, int time)
: player_id(id)
, time_cycle(time)
{}
std::string Player::getPlayerId() const
{
return player_id;
}
All of these problems are really basic C++ stuff, nothing to do with NachOS.
Did you modify the Makefile.common in the root nachos directory? I think you should add some value to THREAD_H, THREAD_O and THREAD_C.