this maybe a little trivial but I'm puzzled with such problem.
I want to create two classes Class1, Class2. Both classes should contain a field that contains pointer to instance of the other class. So they should be cross linked.
If I do it like this then I get an error from the compiller saying:
- ISO C++ forbids declaration of 'Class1' with no type
- expected ';' before * token
Please help :)
file: class1.h
#ifndef CLASS1_H
#define CLASS1_H
#include "class2.h"
class Class1 {
public:
Class1();
private:
Class2* link;
}
#endif
file: class2.h
#ifndef CLASS2_H
#define CLASS2_H
#include "class1.h"
class Class2 {
public:
Class2();
private:
Class1* link;
}
#endif
Add class declaration (as opposed to definition) before you use it. For example, you could have:
#ifndef CLASS1_H
#define CLASS1_H
class Class2;
class Class1
{
public:
Class1();
private:
Class2* link;
}
#endif
and do the same for Class2.h.
The problem is the circular dependency; each header is trying to include the other, which is impossible.
You don't need the full definition of each class in order to declare a pointer to it; you can replace each #include line with a forward declaration (class Class1; and class Class2;), and then everything should compile happily.
Related
I am trying to use a struct of one class in another class. My first class looks like this:
Class1.h
#ifndef CLASS1_H
#define CLASS1_H
class Class1
{
public:
Class1();
~Class1();
struct St{
int x;
}
St struct1;
private:
};
#endif
Now in the header of the second class, I want to use this struct and variable.
Class2.h
#ifndef CLASS2_H
#define CLASS2_H
#include "Class1.h"
class Class2
{
public:
Class2();
~Class2();
St struct2;
private:
};
However, it says:
identifier "St" is undefined.
When I use it this way:
Class1::St struct1;
the error goes away. What are the issues with my code?
What are the issues with my code?
The issue is St is a nested class. Its fully qualified name is ::Class1::St1. Within the scope of Class2, the unqualified name lookup does not use the scope of Class1, so no declaration of St will be found.
You can fix the issue by doing the following:
When I use it this way:
Class1::St struct1;
the error goes away.
Well I have 2 classes in 2 header and 2 cpp files
#class1.h
#ifndef class1_h
#define class1_h
class myclass;
#endif
#class2.h
#ifndef class2_h
#define class2_h
class anotherclass;
#endif
#class1.cpp
class myclass
{
anotherclass test1;
}
#class2.cpp
class anotherclass
{
myclass test2;
}
And of course a simple main
Well I think it's obvious why this thing wont even compile
my question here is how to make it compile?
Having the classes in different files is mandatory..
If the class definitions (the bodies that is) must be in separate files then the members of the declared type can only be a pointer (or a reference but that is unusual). You would then need a function in the source file where the class is actually defined that returns a pointer-to-instance of the type.
MyClass.h:
#if !defined(MYCLASS_H)
#define MYCLASS_H
class MyClass;
MyClass * CreateMyClass();
#endif
OtherClass.h:
#if !defined(OTHERCLASS_H)
#define OTHERCLASS_H
class OtherClass;
OtherClass * CreateOther();
#endif
myclass.cpp
#include "otherclass.h"
class MyClass
{
OtherClass * ptrOther;
public:
MyClass()
: ptrOther(CreateOther())
{}
};
otherclass.cpp:
#include "myclass.h"
class OtherClass
{
MyClass * ptrMyClass;
public:
OtherClass()
: ptrMyClass(CreateMyClass())
{}
};
Note that doing things this way you would not actually be able to do anything with ptrOther or ptrMyClass ((possibly not even free them correctly), It would be much more typical to place the class definitions in the header and separate out the member definitions (for functions and statics), like the following:
MyClass2.h:
#if !defined(MYCLASS2_H)
#define MYCLASS2_H
#include "OtherClass.h"
class MyClass2
{
OtherClass * ptrOther;
public:
MyClass2();
};
#endif
cMyClass.cpp:
#include "MyClass2.h"
MyClass2::MyClass2()
: ptrOther(CreateOther())
{}
Header files define class interfaces. Source code '.cpp' files are using for the implementation. Your source code has the implementation and the class interface.
I'm a first-year college student that doesn't know everything about CS yet, so please bear with my newness to it, and this is my first question on here.
For an assignment, we are making faux version of Pokemon Go to practice using polymorphism in c++, and I'm running into some compiler errors. Here are the three files with just a sample of the code in them:
#ifndef EVENT_H
#define EVENT_H
#include <string>
#include "Trainer.h"
class Event{
protected:
std::string title;
public:
Event();
~Event();
virtual void action(Trainer) = 0;
};
#endif
Trainer.h:
#ifndef TRAINER_H
#define TRAINER_H
#include "Pokemon.h"
class Trainer{
private:
Pokemon* pokemon;
int num_pokemon;
public:
Trainer();
~Trainer();
//include accessors and mutators for private variables
};
#endif
Pokemon.h:
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event{
protected:
std::string type;
std::string name;
public:
Pokemon();
~Pokemon();
virtual bool catch_pokemon() = 0;
};
#endif
The trainer.h file is a parent class for each pokemon type (eg Rock) which just defines a few virtual functions. The error I'm getting is when I'm compiling all of this and I get something that says:
Pokemon.h : 5:30: error: expected class-name befoer '{' token:
class Pokemon : Event {
Pokemon need to be a derived class to an event, so that an event pointer can point in another Location class can point to either a pokemon, pokestop, or cave for the assignment, and I have been looking online for hours and can't figure out what to do. I would appreciate the help! Let me know if you need more info or something because again, this is my first time posting a question.
You need some forward declarations.
In Event.h, you can put class Trainer; instead of #include "Trainer.h". In Trainer.h, you can put class Pokemon; instead of #include "Pokemon.h".
You will probably need to include the appropriate headers in the corresponding source files in order to actually use the other classes. But by avoiding the includes in the header files, you get out of the circular dependency trouble.
Pokemon.h must continue to #include "Event.h", since you're inheriting Event, which requires a complete definition.
Use forward declaration, to tell classes the type they need to use will be defined later. You can use forward declaration in situations where the size is know, pointers and references are always the same size regardless of the type they point to so use them.
#ifndef EVENT_H
#define EVENT_H
#include <string>
class Trainer;
class Event
{
protected:
std::string title;
public:
Event();
virtual ~Event();
virtual void action(Trainer* const trainer) = 0;
};
#endif
then
#ifndef TRAINER_H
#define TRAINER_H
class Pokemon;
class Trainer
{
private:
Pokemon* const pokemon;
int numPokemon;
public:
Trainer();
~Trainer();
};
#endif
then
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event
{
protected:
std::string type;
std::string name;
public:
Pokemon();
virtual ~Pokemon();
virtual bool catchPokemon() = 0;
};
#endif
when using polymorphism (virtual functions) you must always make the base class destructor virtual too. It is also nice to make the derived classes destructor virtual as well, but it is not required.
I have class1 that needs header of class2.And class2 that needs header of class1 to be included.
I included header of class2 in class1 and header of class1 in class2 and troubles began (in class2 I get error that says that class1 instance do not name a class)
Please can someone explain how to deal with this situation because I googled this question but didn't get what to do
thank you
One often applicable solution to this is to simply forward-declare the classes. For example:
class1.h
#ifndef CLASS1_H
#define CLASS1_H
class Class2;
class Class1 {
public:
// ...
private:
// ...
std::unique_ptr<Class2> owned_child_;
// ...
};
#endif
class2.h
#ifndef CLASS2_H
#define CLASS2_H
class Class1;
class Class2 {
public:
// ...
private:
// ...
const Class1* unowned_parent_;
// ...
};
#endif
Note, however, that this strategy only works so long as you do not write code that requires the definition of the class to be available, which can be achieved when using pointers or references to the class's type. As soon as you use the class type without a reference or pointer, you will need to have available the full declaration of the class already processed and available.
I have two classes and both of them uses some of the other class, on example:
// class1.h
class Class1;
#include "class2.h"
class Class1 {
public:
static Class2 *C2;
...
};
// class2.h
class Class2;
#include "class1.h"
class Class2 {
public:
static Class1 *C1;
...
};
And when I define it like in example above, it works (I also have some #ifndef to avoid infinite header recurency). But I also want to add some inline functions to my classes. And I read here that I should put definition of inline function in header file, because it won't work if I'll put them in cpp file and want to call them from other cpp file (when I do it I get undefined reference during linking). But the problem here is with something like this:
// class1.h
...
inline void Class1::Foo() {
C2->Bar();
}
I get error: invalid use of incomplete type ‘struct Class2’.
So how can I do it?
You need to delay including the header, but then include it and define your inline methods. By doing this in each header, they are self-sufficient and including one will always include the other, with include guards preventing infinite recursion.
A.hpp
#ifndef INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
#define INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
struct B;
struct A {
B* p;
void foo();
};
#include "B.hpp"
inline
void A::foo() {
if (p) p->bar();
}
#endif
B.hpp
#ifndef INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
#define INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
struct A;
struct B {
A* p;
void bar();
};
#include "A.hpp"
inline
void B::bar() {
if (p) p->foo();
}
#endif
You have it mix'd up. What you want is:
// class1.h
class Class2;
class Class1 {
public:
static Class2 *C2;
...
};
// class2.h
class Class1;
class Class2 {
public:
static Class1 *C1;
...
};
And include the respective headers in the source. The line:
class Class1; // or Class2
Declares an incomplete type, and you can have pointers and references to incomplete types. Upon usage, though, it needs to be complete. So just say "hey it'll exist!" in the header, and in the source tell it what it is.
My suggestion is that you place common methods and members into a base class, then derive C1 and C2 from the base class. This may fix the circular dependency issue.