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.
Related
I want to create some objects that can delegate some work to its nested subobjects, but it pushes me into the circular dependency issues. Using of #ifndef directive works fine if I have only two classes (ClassA and ClassB), but this pattern doesn't work when ClassC is added. Is it possible to achieve such type of structure as shown in the code below and don't get an "undefined type" errors?
ClassA.h
#pragma once
#include "CoreMinimal.h"
#include "ClassB.h"
class UClassB;
#include ClassA.generated.h
UCLASS()
class PROJ_API UClassA : public UObject
{
GENERATED_BODY()
UPROPERTY()
UClassB* ObjB;
public:
void DoDelegation()
{
auto* ThisInstance = this;
ObjB = NewObject<UClassB>();
ObjB->DoWorkClassB(ThisInstance);
}
}
ClassB.h
#pragma once
#include "CoreMinimal.h"
//works nice
#ifndef CLASSA_H
#define CLASSA_H
#include "ClassA.h"
class UClassA;
#endif
//trying to use similar pattern which works with ClassA.h and ClassB.h
#include "ClassC.h"
class UClassC;
#include ClassB.generated.h
UCLASS()
class PROJ_API UClassB : public UObject
{
GENERATED_BODY()
UPROPERTY()
UClassC* ObjC;
public:
void DoDelegation()
{
auto* ThisInstance = this;
ObjC = NewObject<UClassC>();
ObjC->DoWorkClassC(ThisInstance);
}
void DoWorkClassB(UClassA* &ObjectClassA)
{
// do some stuff with ObjectClassA
}
}
ClassC.h
#pragma once
#include "CoreMinimal.h"
//trying to use similar pattern which works with ClassA.h and ClassB.h
//got "undefined type" error
#ifndef CLASSB_H
#define CLASSB_H
#include "ClassB.h"
class UClassB;
#endif
#include ClassC.generated.h
UCLASS()
class PROJ_API UClassC : public UObject
{
GENERATED_BODY()
public:
void DoWorkClassC(UClassB* &ObjectClassB)
{
// do some stuff with ObjectClassB
}
}
creating classes that refer to each other
Is it possible to achieve such type of structure as shown in the code below and don't get an "undefined type" errors?
Certainly. Referring to an object (with a pointer for example) of some class only requires declaration of the other class, not definition.
Simple solution is to declare both classes before defining either of them.
It's still not fully clear for me, but at least i understood why forward declaration wasn't worked for the first time. Inline implementation of methods that do something with such referencing classes is strictly not recommended. It compiles well If function is implemented in cpp.
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?
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.
So I am getting the following errors:
..\Actor.h:35: error: `Attack' is not a member of `RadiantFlux'
..\Actor.h:35: error: template argument 1 is invalid
..\Actor.h:35: error: template argument 2 is invalid
..\Actor.h:35: error: ISO C++ forbids declaration of `attacks' with no type
On this line (among others):
std::vector<RadiantFlux::Attack> attacks;
Here are the relevant files:
Actor.h:
#ifndef ACTOR_H_
#define ACTOR_H_
#include <string>
#include <vector>
#include "Attack.h"
namespace RadiantFlux {
...
class Actor {
private:
std::string name;
int health;
std::vector<RadiantFlux::Attack> attacks;
Attributes attributes;
public:
...
};
}
#endif /* ACTOR_H_ */
Attack.h:
#ifndef ATTACK_H_
#define ATTACK_H_
#include <string>
#include <stdlib.h>
#include <time.h>
#include "Actor.h"
namespace RadiantFlux {
...
class Attack {
private:
...
public:
...
};
}
#endif /* ATTACK_H_ */
Why am I getting these errors and what can I do to fix them? I am assuming it has something to do with the namespaces...
You have a cyclic dependency of your header files.
Attack.h includes Actor.h and vice versa.
Use Forward Declaration of class to avoid circular dependency problems.
Since the OP's comments, here is what needs to be done:
class Actor;
class Attack
{
};
If your code fails to compile after doing this, You need to read the linked answer and Understand why the error and how to solve it. The linked answer explains it all.
The classes Actor and Attack both refer to each other, so you will need to add a forward declaration in one of the file.
For example, in Actor.h:
class Attack;
class Actor
{
...
};
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.