This question already has answers here:
C++ class header files organization
(6 answers)
Closed 8 years ago.
I need to include recursively class header files.
"Foo.h"
#ifndef FOO_H
#define FOO_H
#include "Bar.h"
class Foo {
public:
Bar* barMember;
};
#endif
"Bar.h"
#ifndef BAR_H
#define BAR_H
#include "Foo.h"
class Bar {
public:
Foo* fooMember;
};
#endif
In this case I am getting errors like
'class' does not name a type
Consider that in this case Foo is the main class that includes a lot of other classes as a members. But with one member I need to have bidirectional connection.
So why do I have such problems?
Use forward declarations:
#ifndef FOO_H
#define FOO_H
class Bar;
class Foo
{
public:
Bar* barMember;
};
#endif
and:
#ifndef BAR_H
#define BAR_H
class Foo;
class Bar
{
public:
Foo* fooMember;
};
#endif
You will only need to include the respective header files in the .cpp files containing the implementations, so there won't be mutual inclusions.
Related
I'm looking to create two classes, each of which contains an object of the other class type. How can I do this? If I can't do this, is there a work-around, like having each class contain a pointer to the other class type? Thanks!
Here's what I have:
File: bar.h
#ifndef BAR_H
#define BAR_H
#include "foo.h"
class bar {
public:
foo getFoo();
protected:
foo f;
};
#endif
File: foo.h
#ifndef FOO_H
#define FOO_H
#include "bar.h"
class foo {
public:
bar getBar();
protected:
bar b;
};
#endif
File: main.cpp
#include "foo.h"
#include "bar.h"
int
main (int argc, char **argv)
{
foo myFoo;
bar myBar;
}
$ g++ main.cpp
In file included from foo.h:3,
from main.cpp:1:
bar.h:6: error: ‘foo’ does not name a type
bar.h:8: error: ‘foo’ does not name a type
You cannot have two classes directly contain objects of the other type, since otherwise you'd need infinite space for the object (since foo has a bar that has a foo that has a bar that etc.)
You can indeed do this by having the two classes store pointers to one another, though. To do this, you'll need to use forward declarations so that the two classes know of each other's existence:
#ifndef BAR_H
#define BAR_H
class foo; // Say foo exists without defining it.
class bar {
public:
foo* getFoo();
protected:
foo* f;
};
#endif
and
#ifndef FOO_H
#define FOO_H
class bar; // Say bar exists without defining it.
class foo {
public:
bar* getBar();
protected:
bar* f;
};
#endif
Notice that the two headers don't include each other. Instead, they just know of the existence of the other class via the forward declarations. Then, in the .cpp files for these two classes, you can #include the other header to get the full information about the class. These forward declarations allow you to break the reference cycle of "foo needs bar needs foo needs bar."
That doesn't make sense. If A contains B, and B contains A, it would be infinite size. Imagine putting having two boxes and trying to put both into each other. Doesn't work, right?
Pointers work though:
#ifndef FOO_H
#define FOO_H
// Forward declaration so the compiler knows what bar is
class bar;
class foo {
public:
bar *getBar();
protected:
bar *b;
};
#endif
I have the following code:
foo.h
#ifndef FOO_H
#define FOO_H
#include "bar.h"
class Foo
{
public:
Foo(Bar bar);
};
#endif //FOO_H
bar.h
#ifndef BAR_H
#define BAR_H
#include "foo.h"
class Bar
{
public:
Bar(Foo foo);
};
#endif //BAR_H
If I compile that, I get the following error message:
expected ')' before 'foo' bar.h line 9
After looking on this website, I fixed it by using a forward declaration of Foo in bar.h, and Bar in foo.h.
My question is, why does the compiler make this error sound like a syntax error, whilst it's actually not ? I would think that catching such an error and return a proper error message would be quite simple.
You have headers with unresolved circular dependency. That is when your code somewhere includes "foo.h" first then after preprocessing it will become
class Bar // expanded from #include "bar.h"
{
public:
Bar(Foo foo); // Foo is not declared at this point
};
class Foo // rest of foo.h content
{
public:
Foo(Bar bar);
};
if your code includes "bar.h" first then after preprocessing it will become
class Foo // expanded from #include "foo.h"
{
public:
Foo(Bar bar); // Bar is not declared at this point
};
class Bar // rest of bar.h content
{
public:
Bar(Foo foo);
};
So there is an error in both cases.
To get around this issue you need to utilize proper forward declarations:
// foo.fwd.h
#ifndef FOO_FWD_H
#define FOO_FWD_H
class Foo;
#endif // FOO_FWD_H
// bar.fwd.h
#ifndef BAR_FWD_H
#define BAR_FWD_H
class Bar;
#endif // BAR_FWD_H
and include them into headers instead of header with complete class declaration:
// foo.h
#ifndef FOO_H
#define FOO_H
#include "bar.fwd.h"
class Foo
{
public:
Foo(Bar bar);
};
#endif //FOO_H
// bar.h
#ifndef BAR_H
#define BAR_H
#include "foo.fwd.h"
class Bar
{
public:
Bar(Foo foo);
};
#endif //BAR_H
and then include headers with class definition only into .cpp or implementation file.
C++ is very hard to parse. When compiler does not know that Foo is name of some type then it expects that we try to declare members with that name in Bar. Code does not parse as any of valid variants of member declarations.
Old compilers just diagnosed such cases as "syntax error". Modern compilers try to be friendlier. The diagnostic likely tries to help us to correct the code towards one of such (or some other similar) valid member declaration.
class Bar
{
public:
Bar (Foo());
Bar (*Moo);
Bar Roo();
};
Unfortunately it guessed totally wrongly since Foo was not meant as member name but as a type of parameter of constructor.
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 looking to create two classes, each of which contains an object of the other class type. How can I do this? If I can't do this, is there a work-around, like having each class contain a pointer to the other class type? Thanks!
Here's what I have:
File: bar.h
#ifndef BAR_H
#define BAR_H
#include "foo.h"
class bar {
public:
foo getFoo();
protected:
foo f;
};
#endif
File: foo.h
#ifndef FOO_H
#define FOO_H
#include "bar.h"
class foo {
public:
bar getBar();
protected:
bar b;
};
#endif
File: main.cpp
#include "foo.h"
#include "bar.h"
int
main (int argc, char **argv)
{
foo myFoo;
bar myBar;
}
$ g++ main.cpp
In file included from foo.h:3,
from main.cpp:1:
bar.h:6: error: ‘foo’ does not name a type
bar.h:8: error: ‘foo’ does not name a type
You cannot have two classes directly contain objects of the other type, since otherwise you'd need infinite space for the object (since foo has a bar that has a foo that has a bar that etc.)
You can indeed do this by having the two classes store pointers to one another, though. To do this, you'll need to use forward declarations so that the two classes know of each other's existence:
#ifndef BAR_H
#define BAR_H
class foo; // Say foo exists without defining it.
class bar {
public:
foo* getFoo();
protected:
foo* f;
};
#endif
and
#ifndef FOO_H
#define FOO_H
class bar; // Say bar exists without defining it.
class foo {
public:
bar* getBar();
protected:
bar* f;
};
#endif
Notice that the two headers don't include each other. Instead, they just know of the existence of the other class via the forward declarations. Then, in the .cpp files for these two classes, you can #include the other header to get the full information about the class. These forward declarations allow you to break the reference cycle of "foo needs bar needs foo needs bar."
That doesn't make sense. If A contains B, and B contains A, it would be infinite size. Imagine putting having two boxes and trying to put both into each other. Doesn't work, right?
Pointers work though:
#ifndef FOO_H
#define FOO_H
// Forward declaration so the compiler knows what bar is
class bar;
class foo {
public:
bar *getBar();
protected:
bar *b;
};
#endif
This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 4 years ago.
FILE #1 (foo.h):
#ifndef FOO_H_
#define FOO_H_
#include "baseclass.h"
#include "bar.h"
class Bar;
class Foo : public baseclass {
public:
bar *varBar;
};
#endif
FILE #2 (bar.h):
#ifndef BAR_H_
#define BAR_H_
#include "foo.h"
class Foo;
class Bar {
public:
Foo *varFoo;
};
#endif
FILE #3 (baseclass.h):
#ifndef BASECLASS_H_
#define BASECLASS_H_
#include "foo.h"
class Foo;
class baseclass {
public:
list<Foo*> L;
};
#endif
But I get an compile error in file #1 in line class Foo : public baseclass:
Error: expected class-name before »{« token
If I add class baseclass; bevor class declaration, I get this error:
Error: invalid use of incomplete type »struct baseclass«
So my question is, how can I resolve circular dependencies with baseclasses?
Ask if you don't get somepoint. I allready tried to change the order of includeing the headers, but no luck so far.
Thanks for any hint.
EDIT: Note: I am using include guards
EDIT2: It is not limited to pointers, so I remove them, just in case.
EDIT3: Added baseclass (forgot O.o)
EDIT4: Now it should be clear and without anymore flaws, the problem persisits with this code.
The usual way is to add the following around your header files:
#ifndef FOO_H_
#define FOO_H_
#include "baseclass.h"
#include "bar.h"
class Bar;
class Foo : public baseclass {
public:
bar *varBar;
};
#endif
and
#ifndef BAR_H_
#define BAR_H_
#include "foo.h"
class Foo;
class Bar {
public:
Foo *varFoo;
};
#endif
Most compilers (gcc, VC) also accept #pragma once at the beginning of the file, but I'm pretty sure it is not part of the current C++ standard.
EDIT:
Sure enough, as the ISO/IEC 14882 states, a #pragma "causes the implementation to behave in an implementation-defined manner. Any pragma that is not recognized by the implementation is ignored."
It is currently still the same with C++0x.
So I would stick with the first old-fashioned way of doing that ;-)
What you seem to have posted is to have a Bar member in the Foo, and a Foo member in the Bar. That is a circular dependency you need to break - if every Foo contains a Bar which contains a Foo then constructing either never terminates.
class Foo : public baseclass {
public:
Bar varBar;
};
class Bar {
public:
Foo varFoo;
};
Instead you need to use a pointer or reference to the Foo or Bar in at least one of them:
class Bar;
class Foo : public baseclass {
public:
Bar& varBar;
};
class Bar {
public:
Foo varFoo;
};
As the circularity is broken and you're only using a reference to the object, you don't need to have the full definition of the referred-to type, and can use a forward declaration.
Include guards are good for users, but try and not rely on them when developing. If the compiler has to check whether or not something has been included, it's still doing work even if it has optimisations for guards/pragmas. You do need to have some understanding of what depends on what to break the initial cycle, and putting guards on the files won't help you with that.
Do you have include guards on your headers? The code above includes a.h and b.h recursively, thus defining a whole bunch of headers.
The forward declaration class b; removes the need for the #include "b.h" in FILE1. Similarly, #include "a.h" should be removed from FILE2.
#ifndef _BAR_H_
#define _BAR_H_
#include "baseclass.h"
class Bar;
class Foo : public baseclass {
public:
Bar *varBar;
};
#endif
If a class is forward declared and you are using only a pointer or a reference to a member of that class, then you do not need to include the header for it. The same goes for the class in the other file. But yes, make sure that you use include guards in all of your header files (#ifndef...#endif) to prevent multiple inclusions of headers during compilation.
baseclass.h doesn't need anything from foo.h, so remove #include "foo.h" from baseclass.h.
You have a Foo variable in your Bar, and a Bar in your Foo. That isn't going to work: you can't have an egg in a box and a box in an egg. One or both of them should be a pointer.