Why is this error so unclear? - c++

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.

Related

C++ tamplate class instances which reference to each other [duplicate]

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

Multiple definition of variable

Here's my code:
main.cpp
#include "foo.h"
int main()
{
return 0;
}
foo.h
#ifndef FOO_H
#define FOO_H
class Foo
{
public:
Foo();
int bar;
}
#endif
foo.cpp
#include "foo.h"
Foo::Foo()
{
bar = 3;
}
Compiling this gives me the following error:
multiple definition of 'bar'
But I have include guards around the header file which defines bar, therefore how can it be defined more than once?
It's down to the missing semicolon at the end of the class declaration foo in foo.h.
That's confusing the compiler (it seems to be attempting to parse your constructor definition as the name of an object of type foo).
C++ ain't Java you know!

Recursive Class header include [duplicate]

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.

Fixing order of inclusion when there is circular dependency in C++ template classes

I came across a circular dependency issue, where the order of inclusion of headers matters. This problem is similar, but it does not document the solution where one class instantiates an object of the other.
Problem:
I have two classes: Foo and Bar. Bar is templatized. (Foo may or may not be templatized).
Foo has an instance of Bar, and Bar has a pointer of type Foo, and the implementation of Bar needs to access members of Foo through this pointer.
Foo and Bar have to be implemented within separate files. As Bar is templatized, its declaration and implementation have to be in the same file.
In the following code, if main.cpp includes Bar.h before Foo.h the code compiles, and does not when Foo.h is included before Bar.h. Is there a way to make the code compile, irrespective of the order in which headers are included in main.cpp?
Foo.h
#ifndef FOO_H
#define FOO_H
#include"Bar.h"
class Foo
{
public:
Bar<> B;
void fooStuff(){};
};
#endif
Bar.h
#ifndef BAR_H
#define BAR_H
class Foo;
template<int N=0> class Bar
{
public:
Foo * F;
void barStuff();
};
#include"Foo.h"
template<int N> void Bar<N>::barStuff()
{
F->fooStuff();
};
#endif
main.cpp
#include"Foo.h"
#include"Bar.h"
int main()
{
Foo F;
F.B.barStuff();
};
Yes: declare Foo before Bar, since Bar only uses a pointer, which doesn't need a full definition. Then define Foo after Bar - it uses an object, and so it does need the definition.
class Foo;
template<int N> class Bar
{
public:
Foo * M;
void barStuff();
};
class Foo
{
public:
Bar<42> B;
void fooStuff(){}
};
template<int N> void Bar<N>::barStuff()
{
M->fooStuff();
}
In general, you need the full definition for anything that needs any properties of the class, such as its size or members, and only a declaration to use the class name when declaring functions, pointers or references.
I need Bar to be included before Foo, no matter in what order they're included in main.cpp. The following hack seems to work:
In Foo.h, include Bar.h outside the header guards. As Bar has header guards too, it does not get included multiple times.
Foo.h
#include"Bar.h"
#ifndef FOO_H
#define FOO_H
class Foo
{
public:
Bar<> B;
void fooStuff(){};
};
#endif
Bar.h
#ifndef BAR_H
#define BAR_H
class Foo;
template<int N=0> class Bar
{
public:
Foo * F;
void barStuff();
};
#include"Foo.h"
template<int N> void Bar<N>::barStuff()
{
F->fooStuff();
};
#endif
main.cpp
#include"Foo.h"
#include"Bar.h"
int main()
{
Foo F;
F.B.barStuff();
};

How to create two classes in C++ which use each other as data?

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