Suppose I have a class A and a class B.
The .h of A, needs the .h of B, and the .h of B needs the .h of A. (need = #include).
All .h have the guards:
#ifndef _classX_
#define _classX_
...
...
#endif
But if I compile the .cpp of A, then when it includes the .h of B, the B class cannot include the .h of A class because the A class has already use the guard.
How can i solve this?
You will need a forward declaration of one of the classes.
// a.h
// do not #include b.h
class B; // forward declaration
class A {
....
B * b;
};
Note that the class A cannot contain an actual B instance - it must be a pointer or a reference. You also cannot call any functions via the B pointer in the header - they will have to go in a .cpp source file which #includes both headers.
One of them need to get around not to include it. For many cases this is possible such that you can move the #include into the .cpp file
class A {
// no need for header of B here
void f(B b);
// no need for header of B here either
B *b;
};
Generally for the function declarations whose definitions are in the .cpp files, you don't need any #includes in the header. For class members you only need headers if you want to have them as value objects embedded. You need to change those to pointers (or smart-pointers) and new them within the .cpp file in that case. For the compiler to know what B is in my above example, you just need to put a forward declaration before the definition of A like this:
class B;
Related
I have a C++ project that has multiple files.
File A.h
#ifndef A_H
#define A_H
class A
{
void somefunctionA();
};
A a;
#endif
File B.h
#ifndef B_H
#define B_H
class B
{
void somefunctionB();
};
B b;
#endif
I want to use object a in class B and object b in class A
So basically I want to use variables a and b anywhere in the program.
main.cpp
#include "A.h"
#include "B.h"
...
But there is a conflict. Object "a" isn't seen in class B.
What can be done in this situation and is there a better approach?
You can declare a class anywhere, like in an unrelated header file.
For example:
#ifndef B_H
#define B_H
// Declaration of class A
class A;
extern A a;
class B
{
void somefunctionB();
};
extern B b;
#endif
Now in the implementation of e.g. B::somefunctionB you can use the variable a without seeing the definition of the variable. You do need the definition of the A class though.
A declaration is basically you telling the compiler that something exists, what type it is and what name it have. It's like function prototypes, you declare that somewhere there is a definition of a function, but after the function prototype declaration you can call the function without having seen the function definition (implementation).
A definition, on the other hand, is what tells the compiler (and later the linker) that "this is it". The definition of a variable is not only telling the compiler that the variable exists, but also instructs the compiler to reserve space for the variable in the resulting executable program. A definition of a function is the actual implementation of of the function, where you have the code inside the function.
Incidentally, if a variable or function haven't been declared then the compiler sees the definition of the variable or function, then the definition is also the declaration.
If, as you state, you have all code for the classes inline in the class definition you will have a problem using the global variables with only a class declaration, you need the complete class definition. But if you use class A in class B and the other way around, you have a circular dependency that is hard to break: Class A needs class B to work, but class B needs class A to work.
The easiest solution to break this circular dependency is to put the code from class A that uses class B in a separate source file, and the same for the code in class B that uses class A. This way the header files will not need to include each other giving you the circular dependency, and the source files can include both header files without problems.
Use the singleton pattern for implementing classes that should have only a single global instance:
class A
{
public:
static A& instance()
{
static A instance_;
return instance_;
}
virtual ~A() {}
private:
A() {} // prevent direct instantiation
A(const A&); // prevent copy construction
A& operator=(const A&); // prevent assignment
};
Then use A::instance() wherever you need to interact with the object instance.
Of course this pattern should be used sparingly. Make sure that you really need a global object before creating one and that there is no other way which will give you the same functionality.
Please note that this pattern is not suitable for global objects that depend on each other as the order of static initialization is undefined.
I have a class called A, which has its .cpp and .hpp files. It depends on classes B and C. Now, I'm wondering, should I #include B.hpp and #include C.hpp in A.cpp or A.hpp? I think it would be beneficial for me to #include in the A.hpp file, because I'm creating a vector of B*'s, and I'm not sure that the compiler will know the correct size of B if I only forward declare it (so I couldn't pointer increment correctly)... By "forward declaration", I mean writing class B; and class C; in the beggining of A.hpp.
As already mentioned, you can often work-around having to #include stuff by using forward declarations, and indeed the best practice is to minimize the amount of other headers included.
But: To answer your questions headline: yes you may, and the common mechanism to avoid "circular inclusion" is the following
A.hpp:
#ifndef A_HPP_INCLUDED
#define A_HPP_INCLUDED
... // code
#endif
Now if say B.hpp includes A.hpp, and subsequently, C.hpp looks like:
#ifndef C_HPP_INCLUDED
#define C_HPP_INCLUDED
#include "A.hpp"
#include "B.hpp"
...
#endif
Then you won't get an error stating that e.g. 'class A' has already been defined.
If it's a vector of B*, you don't need to include B.hpp in the other header. A forward declaration is fine. Pointers have the same size, regardless of what they point to.
It's preferred to have includes only when necessary, and this certainly looks like it's not.
I don't know if i understand your class hierarchy, in my mind is like this:
B.hpp
class B
{
B();
};
B.cpp
B::B() {};
C.hpp
class C
{
C();
};
A.cpp
A::A() {};
A.hpp
class A
{
A();
B *b;
C *C;
};
A.cpp
#include "B.hpp"
#include "C.hpp"
A::A() :
b(NULL), c(NULL)
{
};
Is this correct? (if not, please think about provide some code ;) If your class A have pointers to class B and class C a forward declaration must be the only thing you need.
I'm not sure that the compiler will know the correct size of B if I only forward declare it
Yes, as long as you include the B.hpp and C.hpp in the A.cpp file the compiler would be able to deduce its size (the class size, the pointer size is always the same). Why? Just because in the cpp file it knows the correct size due the #include. I've found this answer that would be useful to understand what I', trying to say.
Would be fine in the hpp file instead? Maybe, if your A.hpp would not be included in other files the class B and class C does not bother and spreading into another files. So, if it is the case that would not be neccessary. But IMHO the best practice is to forward declare and #include in the cpp files when it is possible.
I have two classes both defined in separate header files. Each file has a field that is type of other class. Now I included in header of each file the header of other file, but compiler is generating errors. What am i missing?
You cannot have each class have "a field that is type of other class"; that would be a recursive definition and not only the compiler would not be able to make any sense out of it, it does not even make logical sense.
Each class having a field that is type of the other class is the kind of impossibility that you only see in M.C. Escher drawings, or animations thereof, like this one:
B. de Smit and H. W. Lenstra - Source: escherdroste.math.leidenuniv.nl
based on Escher's "Print Gallery" Lithograph, 1956, see Wikipedia
One of the two fields will have to be a pointer, so as to break the recursive containment, and avoid the logical impossibility.
Which brings us to the next problem: if class B is to contain an instance of class A, then obviously, A has to be declared before class B, so that A is already known to the compiler when compiling B. But if class A is declared before class B, how can we declare a pointer to B in A? Class B is not known yet at the time that A is compiled! The answer to this is a special construct known as forward declaration which exists precisely in order to accommodate situations like this. A forward declaration of class B looks like this:
class B;
All it is telling the compiler is that there will be a class called B. It does not tell the compiler anything about the contents of class B, so there is very little we can do with it, but we can do one thing: declare pointers to B.
So, the full solution to the problem looks like this:
file "A.h":
/* This is called a "forward declaration". We use it to tell the compiler that
the identifier "B" will from now on stand for a class, and this class will be
defined later. We will not be able to make any use of "B" before it has been
defined, but we will at least be able to declare pointers to it. */
class B;
class A
{
/* We cannot have a field of type "B" here, because it has not yet been
defined. However, with the forward declaration we have told the compiler
that "B" is a class, so we can at least have a field which is a pointer
to "B". */
B* pb;
}
file "B.h":
#include "A.h"
class B
{
/* the compiler now knows the size of "A", so we can have a field
of type "A". */
A a;
}
You shouldn't include the header files inside the other ones, just include the header files in your source files.
In the headers you can use a forward declaration:
// In Class1.h
class Class2;
// In class2.h
class Class1;
Also you can protect against a file being included twice using the preprocessor:
// Class1.h
#ifndef __CLASS_1_H
#define __CLASS_1_H
// content
#endif
I know this is an old topic but maybe you are still interested in solution!
Actually in C++ you can use two classes recursively without using pointers and here is how to do it.
file: a.h
#include <b.h>
class A {
B<> b;
}
file: b.h
class A;
template<typename T = A>
class B {
T a;
}
file: main.cpp
#include "a.h"
A a;
and that's all!
of course this is just for curiosity :)
You probably want to use forward declaration, unless you actually want to put instance of each class in each other. In which case you shouldn't use anything.
If B can only exist within A, I seem to be able to create A and B without using a pointer. B has to simply forward declare A and not include it (avoiding the recursive inclusion).
In my case, a Document has a Section which gets a reference to its Document.
section.h
class Document;
class Section
{
public:
Section(Document& document) : document{document} {}
private:
Document& document;
};
document.h
#include "section.h"
class Document
{
public:
Document() : section{*this} {}
private:
Section section;
};
main.cpp
#include "document.h"
int main()
{
Document document{};
}
This code compiles with g++ and runs on Linux.
A (complex) set of ifdef might enable it for other cases, but I'm not sure about the readability...
Besides the possibility of forward declaration - if it seems that you need two classes mutually within the other it is out of my experience a sign for a mistake in the depth of inheritance.
Eather the classes are a kind of siblings and you should create a parent class for both.
Or you are trying to use a class that is in fact a parent class within one that should have a sibling from this parent class. Then you should create this sibling as a third class.
Suppose I have two .h files: A.h and B.h.
Moreover, A.h includes B.h itself:
B.h - defines class B.
class B {
...
};
A.h - defines class A, which uses class B.
#include B.h
class A {
void SomeFunction(const B& b);
};
Now, I have some .cpp file, that uses both A and B classes (B class maybe used not only in A::SomeFunction(B))
What are the pluses to include both A.h and B.h (instead of only A.h) from the perspective of design-patterns and coding style.
Including both "A.h" and "B.h" makes the dependencies completely clear. There is no reason why "A.h" could not have forward-declared class B, and so including both headers prevents your ".cpp" file from breaking should the transitive include be changed to a forward declaration. In general, it is not a good idea to rely on transitive includes, and instead one should explicitly include all direct dependencies. (Note that this does not apply for "master include" headers that are intended to give transitive includes).
This has nothing to do with design patterns. You would include B.h whenever you need to use the class B, and you would include A.h whenever you need to use the class A. If the class B is a design detail of class A, or otherwise closely associated with it, put it in A.h rather than in a separate header file.
I'd like to point out that when you do have header files, you should have a define to make sure it isn't included twice.
For example:
A.h:
#ifndef _A_H_
#define _A_H_
class A
{
};
#endif
B.h:
#ifndef _B_H_
#define _B_H_
#include "a.h"
class B : public A
{
};
#endif
I think the above makes the most sense because now you can include A and B as many times as you think you'll need, but it won't be compiled multiple times.
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.