I have this situation (two classes with two different header files):
b.h
#include "a.h"
class B {
friend void B* A::create(void);
private:
int x;
};
a.h
#include "b.h"
class A {
public:
void B* create(void);
...
};
basically class A creates "B" objects. I want to give the creation function create() access to modify the private member 'x' of class B. I want to simulate the 'internal' keyword in C#, but at a more granular level.
The problem I have is that I end up with a circular header reference. b.h wants to come after a.h, but a.h wants to come after b.h. What is the proper way of doing this? Do I need to resort to void* ptrs? Since I only create one type of object, i don't think I need the factory pattern. Hopefully I'm missing something simple.
What you need is a "forward declaration". Basically you don't include the classes' headers in other classes' headers (unless you want to use composition, then you have to). In your case, it'd look like this:
// B.h
class A;
class B {
// declare pointers to A freely
};
And the other way round in A.h.
You'd probably need to include A.h in B.cpp (and the other way round) to be able to actually dereference those pointers to access fields, but your problem with circular header inclusion is now gone.
Related
I was wondering about this for some time, and I just cant seem to wrap my head around it. Would anyone share some technical details around my question and possible solutions.
What I have:
A.h
class A {
typedef A* APtr;
};
Program.h
#include "A.h"
Class Test
{
A::APtr _aPtr;
};
What I am trying to do is to eliminate the need of including header A.h in Program.h and want to forward declare the type-defined APtr from A.h with a forward declaration.
Hope I have clarified my question.
Thanks
If your only goal is to eliminate #include A.h from Program.h and you only need pointer access to A inside Program.h, then it suffices to just forward declare the class, and use the pointer type directly.
Program.h
class A;
class Test
{
A* _aPtr;
};
As #Swordfish mentioned in the comment under your question, you cannot use a forward declaration to access members inside a class.
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 classes A and B with both having their header files with include guards. One reads:
#ifndef A_H
#define A_H
#include "B.h"
class A
{
B b;
};
#endif
And the other one:
#ifndef B_H
#define B_H
#include "A.h"
class B
{
A a;
};
#endif
Now I test it with the following main.cpp:
#include "A.h"
int main()
{
A a;
}
The compiling error is as follows:
# make main
g++ main.cpp -o main
B.h:8: error: ‘A’ does not name a type
Is there any solution to this situation, other than using a pointer/reference and a forward declaration?
No, it's not possible: one of them needs to be a pointer or a reference: because if A contains B, which contains A, which contains B, then you have infinite recursion and are trying to specify infinite sized object.
No there is no other option than to use pointer/reference and forward declaration, unfortunately.
You can't do that, you would cause an infinite recursion (A would include B, B would include, A ...), plus the compiler won't allow it because in one of the class declarations the other class will be incomplete. (Not fully defined)
You can just do this if one of them is a pointer or a reference.
I suggest to use the pImpl idiom if possible ( Pointer-to-implementation, other names: Opaque pointer, Handle-body idiom, Cheshire Cat... see here for details. )
It basically allows you to "free" your class declaration from implementation details that are usually visible to users of your class (even though they are not usable, assuming private access).
You simply declare your class as follows:
#ifndef A_H
#define A_H
class A{
public:
//declare public methods -> "interface"
private:
struct Private;
Private * mp_d; //feel free to use smart pointer
};
#endif
The forward declared struct (or class ) is only defined in your source file and contains all implementation details like you data members and functions that are internal to your class.
#include "B.h"
struct A::Private {
B a;
};
A::A() : mp_d( new Private()) {
}
A::~A(){
delete mp_d; //not required if using smart pointer
}
NB: Now the compiler-generated copy constructor and assignement operators don't work any more (as expected). Make sure to either implement them yourself or simply prevent the compiler from generating them by declaring them private (without implementation). (This is basically C++03 style; I think in C++11 you simply add = deleteafter the declaration to prevent compiler-generation.)
EDIT: added "long" name of pImpl
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).