Error in including header file - c++

Hi i have two classes A and B .
in A i am using the header file for B so that i can create an instance for B( e.g. B *b ) and the something i am doing in Class B also i.e including the header file of A and creating the instance for A(e.g. A *a) in B .
while i am including the header file for A in B it gives me the following error in A.h
1>c:\Bibek\A.h(150) : error C2143: syntax error : missing ';' before '*'
1>c:\Bibek\A.h(150)(150) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\Bibek\A.h(150)(150) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

It sounds like you are including the header files in a circular manner (A.h includes B.h, which includes A.h). Using header guards means that when B.h includes A.h in the above scenario, it skips that (due to the now active include guard of A.h), so the types in A.h are not yet defined when parsing B.h.
To fix, you can use forward declarations:
// A.h
#ifndef A_H
#define A_H
// no #include "B.h"
class B; // forward declaration of B
class A {
B* b;
};
#endif
similarly for B.h
This allows you to use pointers of the forward declared class (e.g. in declarations of member variables, member function declarations), but not use it in any other way in the header.
Then in A.cpp you need to have the proper definition of B.h, so you include it:
// A.cpp
#include "A.h"
#include "B.h" // get the proper definition of B
// external definitions of A's member functions
This construction avoids the circular inclusion of the header files while allowing full use of the types (in the .cpp files).
Note: the error about the non-support of default int happens as the compiler does not have the proper definition of A when including B.h, (the C language allows default int definition for unknown types, but this is not allowed in C++)

Related

Overlapping header inclusions

I've run into a simple problem that I need some help with.
I basically have two classes [A & B] (one in each .cpp file with their own .h).
A.h #includes the contents from B.h
B.h #includes the contents from A.h
I've included a header guard, yet, if I try to declare any pointers or objects of type A or B, I'm getting the following errors:
Error 1 error C2061: syntax error : identifier 'B'
Error 3 error C2143: syntax error : missing ';' before '*'
Error 4 error C4430: missing type specifier - int assumed. Note: C++
does not support default-int
Any way around it? The declarations are there - I just don't know why it won't accept it.
If you only require pointers, you only need a forward declaration. Instead of including the headers in each other, simply forward declare the class you need a pointer to. For example, in A.h, you should have:
class B;
And vice versa in B.h.
The reason you're currently having problems is because A.h has a B* in it, so it includes B.h, and B.h has a A*, so it includes A.h. However, the include guard prevents the contents of A.h being included again, so B can't compile.
Let's take a simple example. Here's A.h:
#ifndef A_H
#define A_H
#include "B.h"
class A {
B* b;
};
#endif
Here's B.h:
#ifndef B_H
#define B_H
#include "A.h"
class B {
A* a;
};
#endif
So let's say we're compiling A.h. First we check the inclusion guard, which passes. Then we include B.h, which also has an inclusion guard that passes, so lets show that inclusion:
#include "A.h"
class B {
A* a;
};
class A {
B* b;
};
Now this B.h includes A.h, but the include guard in A.h won't pass again, so the include brings nothing in. Our final preprocessed file looks like:
class B {
A* a;
};
class A {
B* b;
};
Now look at the definition of B. It has an A* in it, but A hasn't yet been declared. This gives you an error.

Resolve linker errors in GNU for redeclaration

I have the following implementation:
header of A:
class A
{
public:
foo();
};
A has its own .cpp file with the implementation for foo()
//header of B
#include "A.h"
class B
{
public foo();
};
Note: B does not have a header of its own
Now in the Class C.cpp, I want to reuse header of A and implementation from B.o. So in C.cpp I do:
//C.cpp
#include "A.h"
....
B b;
b.foo();
..
When I compile the above I am bound to get redeclaration error for the function foo(). I want to know if there is any way to tell GNU compiler to take B.o and omit A.o... Or to tell compiler to consider the first object in the make file that contains the implementation and ignore the rest?
I am using GNU v2.16
Your problem is about redeclaration of A since in C.cpp it will see 2 declarations of A one through A.h and other through B.h, so just guard A.h in a header guard to avoid including it more than once, generally you should always guard your headers:
#ifndef HEADER_A_h_INCLUDED
#define HEADER_A_h_INCLUDED
class A {...};
#endif
Now if you include A.h more than one time this guard will make the second include as nothing!

"missing type specifier" error on constructor declaration

I have 2 classes in 2 different files:
RegMatrix.h:
#ifndef _RM_H
#define _RM_H
#include "SparseMatrix.h"
...
class RegMatrix{
...
RegMatrix(const SparseMatrix &s){...} //ctor
...
};
#endif
SparseMatrix.h:
#ifndef _SM_H
#define _SM_H
#include "RegMatrix.h"
...
class SparseMatrix{
...
SparseMatrix(const RegMatrix &r){...} //ctor
...
};
#endif
On the constructor lines I get the errors:
error C4430: missing type specifier - int assumed.
error C2143: syntax error : missing ',' before '&'
But when i add the classes declarations
class SparseMatrix;
in the RegMatrix.h file and
class RegMatrix;
in the SparseMatrix.h file it works fine.
My question is why is it needed if i have the includes?
10x.
You can't have circular #includes (one file #includes another which #includes the first file). Forward declaring one of the classes instead of the #include will break the chain and allow it to work. Declaring the class name allows you to use the name without having to know about the internal bits of the class.
BTW, the desire for circular #includes is a design smell. Perhaps you could create an interface that the two classes can depend on instead? Then they won't have to mutually depend on each other.
Your header inclusion won't work, see what would happen if i include SparseMatrix.h after resolving includes:
#ifndef _SM_H
#define _SM_H
/// start of #include "RegMatrix.h"
#ifndef _RM_H
#define _RM_H
/// start of #include "SparseMatrix.h" inside "RegMatrix.h"
#ifndef _SM_H
// skipping, because _SM_H is defined and the condition is false
#endif
/// end of #include "SparseMatrix.h" inside "RegMatrix.h"
class RegMatrix{
...
RegMatrix(const SparseMatrix &s){...} //ctor
...
};
#endif
/// end of #include "RegMatrix.h"
...
class SparseMatrix{
...
SparseMatrix(const RegMatrix &r){...} //ctor
...
};
#endif
So basically, SparseMatrix is undefined. You can't do anything about it. Just declare your class forward declaration.
Statements like
class SparseMatrix;
are called forward declarations. It tells the compiler that "somehere" there is a class of that name. It makes the compiler happy and works perfectly as long as the forward declaring file uses either a pointer or a reference to the forward referenced class. Thats because, from compiler point of view, pointers or references are just 4 bytes irrespective of the class contents.
In OP's code, both SparseMatrix and RegMatrix are used only as (const) references, so forward declaration is sufficient to make it work.
However, if the forward declaring file does something which requires the compiler to know its size, e.g.
void foo( SparseMatrix ); // note pass by value
then the compiler would complain :-)
In the particular situation posed by OP, my preference is to abandon the mutual #include altogether and design the interface just based on forward declarations. The implementation (i.e. .cpp files) may have to include both header files, but that is not a problem.
If you include RegMatrix.h first, it will include SparseMatrix.h. Then that will go back to including RegMatrix.h, and skip because the header guard is defined. Then SparseMatrix continues to be defined, except RegMatrix was never even declared. Then you get an error.
You cannot have circular includes. You must forward declare one or both of them, like you did.

Class name does not name a type in C++

I just started programming in C++, and I've tried to create 2 classes where one will contain the other.
File A.h:
#ifndef _A_h
#define _A_h
class A{
public:
A(int id);
private:
int _id;
B _b; // HERE I GET A COMPILATION ERROR: B does not name a type
};
#endif
File A.cpp:
#include "A.h"
#include "B.h"
#include <cstdio>
A::A(int id): _id(id), _b(){
printf("hello\n the id is: %d\n", _id);
}
File B.h:
#ifndef _B_h
#define _B_h
class B{
public:
B();
};
#endif
File B.cpp:
#include "B.h"
#include <cstdio>
B::B(){
printf("this is hello from B\n");
}
I first compile the B class and then the A class, but then I get the error message:
A.h:9: error: ‘B’ does not name a type
How do I fix this problem?
The preprocessor inserts the contents of the files A.h and B.h exactly where the include statement occurs (this is really just copy/paste). When the compiler then parses A.cpp, it finds the declaration of class A before it knows about class B. This causes the error you see. There are two ways to solve this:
Include B.h in A.h. It is generally a good idea to include header files in the files where they are needed. If you rely on indirect inclusion though another header, or a special order of includes in the compilation unit (cpp-file), this will only confuse you and others as the project gets bigger.
If you use member variable of type B in class A, the compiler needs to know the exact and complete declaration of B, because it needs to create the memory-layout for A. If, on the other hand, you were using a pointer or reference to B, then a forward declaration would suffice, because the memory the compiler needs to reserve for a pointer or reference is independent of the class definition. This would look like this:
class B; // forward declaration
class A {
public:
A(int id);
private:
int _id;
B & _b;
};
This is very useful to avoid circular dependencies among headers.
I hope this helps.
error 'Class' does not name a type
Just in case someone does the same idiotic thing I did ...
I was creating a small test program from scratch and I typed Class instead of class (with a small C). I didn't take any notice of the quotes in the error message and spent a little too long not understanding my problem.
My search for a solution brought me here so I guess the same could happen to someone else.
NOTE: Because people searching with the same keyword will land on this page, I am adding this answer which is not the cause for this compiler error in the above mentioned case.
I was facing this error when I had an enum declared in some file which had one of the elements having the same symbol as my class name.
e.g. if I declare an enum = {A, B, C} in some file which is included in another file where I declare an object of class A.
This was throwing the same compiler error message mentioning that Class A does not name a type. There was no circular dependency in my case.
So, be careful while naming classes and declaring enums (which might be visible, imported and used externally in other files) in C++.
You must first include B.h from A.h. B b; makes no sense until you have included B.h.
The problem is that you need to include B.h in your A.h file. The problem is that in the definition of A, the compiler still doesn't know what B is. You should include all the definitions of all the types you are using.
Include "B.h" in "A.h". That brings in the declaration of 'B' for the compiler while compiling 'A'.
The first bullet holds in the case of OP.
$3.4.1/7 -
"A name used in the definition of a
class X outside of a member function
body or nested class definition27)
shall be declared in one of the
following ways:
— before its use in
class X or be a member of a base class
of X (10.2), or
— if X is a nested
class of class Y (9.7), before the
definition of X in Y, or shall be a
member of a base class of Y (this
lookup applies in turn to Y’s
enclosing classes, starting with the
innermost enclosing class),28) or
— if
X is a local class (9.8) or is a
nested class of a local class, before
the definition of class X in a block
enclosing the definition of class X,
or
— if X is a member of namespace N,
or is a nested class of a class that
is a member of N, or is a local class
or a nested class within a local class
of a function that is a member of N,
before the definition of class X in
namespace N or in one of N’s enclosing
namespaces."
when you define the class A, in A.h, you explicitely say that the class has a member B.
You MUST include "B.h" in "A.h"
Aren't you missing the #include "B.h" in A.h?
The solution to my problem today was slightly different that the other answers here.
In my case, the problem was caused by a missing close bracket (}) at the end of one of the header files in the include chain.
Essentially, what was happening was that A was including B. Because B was missing a } somewhere in the file, the definitions in B were not correctly found in A.
At first I thought I have circular dependency and added the forward declaration B. But then it started complaining about the fact that something in B was an incomplete type. That's how I thought of double checking the files for syntax errors.
Try to move all includes outside namespace.
//Error
namespace U2 {
#include <Head.h>
#include <LifeDiode.h>
}
//Solution
#include <Head.h>
#include <LifeDiode.h>
namespace U2 {
}
Not the answer, but for me the thing was that I forgot to add the std:: before the potential type to properly use it.
It actually happend to me because I mistakenly named the source file "something.c"
instead of "something.cpp".
I hope this helps someone who has the same error.

can two classes see each other using C++?

So I have a class A, where I want to call some class B functions. So I include "b.h". But, in class B, I want to call a class A function. If I include "a.h", it ends up in an infinite loop, right? What can I do about it?
Put only member function declarations in header (.h) files, and put member function definitions in implementation (.cpp) files. Then your header files do not need to include each other, and you can include both headers in either implementation file.
For cases when you need to reference the other class in member signatures as well, you can use a forward declaration:
class A;
This lets you use pointer and reference types (A* and A&), though not A itself. It also doesn't let you call members.
Example:
// a.h
struct B; // forward declaration
struct A {
void foo(B* b); // pointers and references to forward-declared classes are ok
};
// b.h
struct A; // forward declaration
struct B {
void bar(A& a); // pointers and references to forward-declared classes are ok
};
// a.cpp
#include "a.h"
#include "b.h"
void A::foo(B* b) {
b->bar(*this); // full declaration of B visible, ok to call members now
}
// b.cpp
#include "a.h"
#include "b.h"
void B::bar(A& a) {
a.foo(this); // full declaration of A visible, ok to call members now
}
Each class (A and B) should have a header file and an implementation file.
Each header file (e.g. A.h) should not include the other header file (e.g. B.h) but may include a forward reference to the other class (e.g. a statement like class B;), and may then use pointers and/or references to the other class in its declaration (e.g. class A may contain a B* as a data member and/or as a method parameter).
Each CPP file (e.g. A.cpp) may include more than one header file (e.g. A.h and B.h). It's recommended that each CPP file should include its own header file first (e.g. A.cpp should include A.h and then B.h, whereas B.cpp should include B.h and then A.h).
Each header file should contain only the declaration, and not the definition of the class: for example it will list the signatures of the class' methods, but not the method bodies/implementations (the method bodies/implementations will be in the .cpp file, not in the header file). Because the header files don't contain implemention details, they therefore don't depend on (don't need to see) details of other classes; at most they need to know that, for example, B is the name of a class: which it can get from a forward declaratin, instead of by including a header file in another header file.
You can also use forward declarations to get around the issue.
Try putting #ifndef, #define and #endif around your .h files.