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.
Related
The title probably isn't very clear, what I'm talking about is:
Say you have a class A depending on B and a class B depending on A.
This causes a circular dependency, but can be solved pretty easily:
/// a.h
#ifndef __A_H
#define __A_H
struct B;
#include "b.h"
struct A
{
B *bptr;
A();
void doStuffWithB();
};
#endif
/// b.h
#ifndef __B_H
#define __B_H
struct A;
#include "a.h"
struct B
{
A *aptr;
B();
void doStuffWithA();
};
#endif
Boom! Circular dependency resolved.
However, what if I now wanted to use an enum declared in B as an argument in A ?
/// a.h ...
struct A
{
B *bptr;
A();
void doStuffWithB(B::Type type); // <-- Compiler smells something funny here
};
/// b.h ...
struct B
{
enum Type
{
// Whatever...
}
B();
void doStuffWithA();
};
Obviously it will not work because the enum isn't yet declared.
The solution for this would be to just put the enum in it's own header file, but it's really nice to have it attached to the class, so would there be any funny way to do something like that ? I searched around but couldn't find a satisfactory answer.
struct B;
#include "b.h"
In the original version of the two header files this #include is completely unnecessary. You'll be happy to learn that the struct B; forward declaration is completely sufficient for declaring the B * class member. The analogous thing applies for the struct A; and the #include in the other header file: the #include is unnecessary.
And once you made this fortunate discovery, the solution in this specific case becomes obvious: simply put back the #include "b.h" back wher eit was.
Only a.h needs to #include the other file, and fully declare the B object in order to make use of its inner enum. The reason for the original compilation error is the unneeded include from b.h to a.h.
When compiling the b.h, its #include of a.h happens before the class and its inner enum gets declared. Then, the #include from a.h to b.h does nothing, because it gets blocked by the include guards. And then the A class gets compiled without the B class, and its inner enum, getting declared.
So, this specific case can be solved, because the dependency on an inner class member is from one of the classes only. What is, actually, an insolvable problem is when two classes have a mutually dependency on each other's inner class member. The only solution is a refactoring, pulling out the inner class type/enums into the global scope, and perhaps using a using or a typedef to alias an inner class to it.
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!
I have class A (in A.h) which depends on class B in (B.h) and vice versa. Forward declaring the used functions works, but this means I have to update everywhere where I forward declared those functions in the future, ex, if I remove, or change argument in those functions they must all be updated to reflect change. I don't feel this is good practice. Is there a way around this?
Thanks
If you only need to work with pointers or references to a class at the declaration level, you can do it like this:
A.h
class B; // forward class declaration
class A {
A(B &);
};
B.h
class A;
class B {
B(A &);
};
B.cpp
#include "B.h"
#include "A.h" // now we get the full declaration of A
B::B(A &a) {
a.foo(5);
}
Mutual dependencies like this are tough to deal with but sometimes unavoidable.
If A and B depend on the implementations of each other, then you've got a system design problem that you need to resolve before proceeding further.
The best way is to have a forward declaration header:
a.fwd.h
#pragma once
class A;
a.h
#pragma once
#include "a.fwd.h"
#include "b.fwd.h"
class A
{
A(B*);
};
etc.
This way, each class provides its own forward declarations - localised alongside the header where it belongs - checked for consistency with the real declarations and definitions by including the forward declaration header in the header, and the header in the implementation.
Consider the following two scenarios (Edited just to complete the whole question and make it clearer)
Case 1: (doesnt compile as rightly mentioned below)
//B.h
#ifndef B_H
#define B_H
#include "B.h"
class A;
class B {
A obj;
public:
void printA_thruB();
};
#endif
//B.cpp
#include "B.h"
#include <iostream>
void B::printA_thruB(){
obj.printA();
}
//A.h;
#ifndef A_H
#define A_H
#include "A.h"
class A {
int a;
public:
A();
void printA();
};
#endif
//A.cpp
#include "A.h"
#include <iostream>
A::A(){
a=10;
}
void A::printA()
{
std::cout<<"A:"<<a<<std::endl;
}
//main.cpp
#include "B.h"
#include<iostream>
using namespace std;
int main()
{
B obj;
obj.printA_thruB();
}
Case 2: (the only modifications...works without compiliation error)
//B.h
#include "A.h" //Add this line
//class A; //comment out this line
Let us assume both the A.cpp and B.cpp are complied together. Do the above two scenarios make any differences? Is there a reason to prefer one method over the other?
Edit:
So how do I make scenario 1 work.
Forward declaration is not a substitute for Header file inclusion.
As the name itself implies, forward declaration is just a Declaration and not a definition.
So, you will declare saying the compiler that it is a class and I just declaring it here and will provide you the definition when am gonna use it. So, normally you forward declare in the Header file and #include in the .cpp file where you will use the members of the forward declared class.
By doing so, what you make is, wherever you are including the header file there will just be a declaration for the class instead of the entire contents #included...
But having said that, when the compiler requires the definition of the class, it should be #included..
So, in your case A obj; requires the definition of class A and hence you should #include..
I myself asked a similar question here and another similar question which has also a nice answer...
Hope it helps..
Case 1 will produce an "incomplete type" error when you compile B.cpp. Because class B contains a class A object, the definition (and in particular the size) of class A is required to be complete before the definition of class B.
Alternatively, you could choose to make some_variable a pointer or reference to class A, and in that case your forward declaration would be sufficient in B.h. You'd still need a full definition of A in B.cpp (assuming you made actual use of the A member functions/data).
You need to use forward declarations in cases where you have classes that refer to each other.
//A.h
class B;
class A {
B* someVar;
}
//B.h
#include <A.h>
class B {
A* someVar;
}
But there's no benefit for doing it in the case you laid out.
Think like a compiler. In order to create an A inside of B, the compiler has to know how to build an A, and the only way to do that is to have the complete definition. The forward declaration tells the compiler that class A exists without describing what it looks like; this is adequate for defining a pointer or a reference. When it comes time to use that pointer or reference, the complete class definition will be required.
If you meant to portray some_variable as a pointer then the frequently recommended practice is to use forward declarations whenever possible to avoid the overhead of includes and longer compile times.
I'm all for best practices but I really like using IDEs that have nice code navigation features and forwards cause a problem there, at least with Netbeans. Whenever I try to navigate to a type declaration, I always end up at the forward and not the .h file containing the actual declaration. I'm willing to accept some extra compile time for the ease of navigation. Maybe this is just a problem with Netbeans :)
.. oh yeah.. If you look at the related questions to the right of your question, you will find lots of additional information of forward declarations.
For case 1, compiler will complain with "incomplete type" for class B because class B contains a class A object, and you did not tell B any detail of class A, so compiler cann't decide the size of object B.
For your case, you can use A& obj or A* obj instead of A obj, since the size of a reference/pointer is const(4/8 for 32bit/64bit CPU).
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.