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.
Related
I have a class SetStructure with this .h file:
#ifndef setstructure_h
#define setstructure_h
#include "Matrix.h"
class SetStructure {
public:
SetStructure();
//some other functions
};
#endif
And a training class with this .h file:
#ifndef training_h
#define training_h
#include "SetStructure.h"
#include "Matrix.h"
class Training {
private:
//some functions
public:
//some functions
};
#endif
When I compile everything, I get this error in my implementation file for Training:
SetStructure training = new SetStructure();
This gives an error
'SetStructure' was not declared in this scope.
Furthermore the compiler thinks all my functions in Training return int even though they're specified as other return types in the Training.h file.
Is there some problem with my #include statements or something else which might lead to this issue?
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.
The title might not be very clear, it's a bit more complex than that. I searched the web for something like my problem but I did not find anything that could help me.
This is not about infinite looping inclusions, I already put preprocessor directives to avoid that.
I have two classes Monster and Character, respectively declared in their own header files, monster.hpp and character.hpp, and respectively implemented in their own source files, monster.cpp and character.cpp.
The problem now is that both classes need each other to work.
monster.hpp :
#ifndef INCLUDE_MONSTER_HPP
#define INCLUDE_MONSTER_HPP
#include "character.hpp"
class Monster
{
private: //Atributes
public: //Methods
void attackM(Monster& id);
void attackC(Character& id);
};
#endif //MONSTER_HPP_INCLUDED
character.hpp :
#ifndef INCLUDE_CHARACTER_HPP
#define INCLUDE_CHARACTER_HPP
#include "monster.hpp"
class Character
{
private: //Attributes
public: //Methods
void attackM(Monster& id);
void attackC(Character& id);
};
#endif //CHARACTER_HPP_INCLUDED
and the main.cpp :
#include <iostream>
#include "character.hpp"
#include "monster.hpp"
using namespace std;
int main(int argc, char **argv)
{
//Whatever
return 0;
}
And I get this error from the compiler :
In file included from character.hpp:7:0,
from main.cpp:3:
monster.hpp:24:16: error: 'Character' has not been declared
void attackC(Character& id);
(the line and column numbers may be wrong)
From what I understand, when monster.hpp is included into character.hpp, the compiler sees that the class Monster uses the class Character, which is not declared yet right at the moment when monster.hpp is included into character.hpp.
And I don't know how to fix that.
Any ideas ?
The way this works is that the header files of char and monster do not include each other. Instead you forward declare the classes and include the headers within the CPP files.
So basically replace #include "monster.hpp" in the.h with class Monster; and #include "monster.hpp" in the .cpp - and same for the other class.
See this question for more details:
What are forward declarations in C++?
#ifndef INCLUDE_MONSTER_HPP
#define INCLUDE_MONSTER_HPP
#include "character.hpp"
class Character;
class Monster
{
private: //Atributes
public: //Methods
void attackM(Monster& id);
void attackC(Character& id);
};
#endif //MONSTER_HPP_INCLUDED
You need to use a forward declaration. See: http://en.wikipedia.org/wiki/Forward_declaration
Basically, the compiler doesn't know what a "Character" is. You temporarily indicate that it's something you can point to by adding the following stub to Character.hpp:
class Character;
Use predeclaration in *.h:
class Character;
class Monster;
use in *cpp the includes:
#include "character.h"
#include "monster.h"
Or put everything in one *.hpp with predeclaration.
I'm trying to include files in my c++ program but I keep encountering the error:
ShapeVisitor.h:9:28: error: ‘Circle’ has not been declared
I think the problem is that the way the classes are structured, it results in a circular dependence. How do I solve this?
The class headers are below...
//Circle.h
#ifndef CIRCLE_H
#define CIRCLE_H
// headers, ...
#include "Shape.h"
class Circle: public Shape {
//class declaration
}
#endif
//Shape.h
#ifndef SHAPE_H
#define SHAPE_H
// headers, ...
#include <iostream>
class Shape {
//a certain method in the class declaration looks like this
virtual void accept(ShapeVisitor& v) = 0;
//rest of class
}
#endif
//ShapeVisitor.h
#ifndef SHAPEVISITOR_H
#define SHAPEVISITOR_H
#include "Circle.h"
class ShapeVisitor {
//a method in the class looks like this:
virtual void visitCircle(Circle *s) = 0;
//rest of class
}
#endif
As you can see, circle includes shape, which includes shapevisitor, which again, includes circle.
Any ideas?
ShapeVisitor.h does not need to include Circle.h, a forward declaration class Circle; will do. Function declarations do not require the full definitions of their argument and return types (not even if the return/arguments are by value!). Only the function's implementation file (in your case: ShapeVisitor.cpp) would need to include Circle.h.
This ancient (but still very true!) column by Herb Sutter is a nice reference.
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.