Here is my code & requirements:
I have 2 classes A & B, they don’t have any inheritance. I used one method of class A to call one method of Class B. Then the class B’s method should callback one of the class A’s method to execute a callback.
Part of code:
classA.h:
#include "classB.h"
class classA
{
public:
classA();
classB *pClassB;
void callClassB();
void callBack();
};
classA.cpp:
#include "classA.h"
classA::classA()
{
pClassB = new classB();
}
void classA::callBack()
{
return;
}
void classA::callClassB()
{
pClassB->callFunction();
}
classB.h:
class classB
{
public:
classB();
void callFunction();
}
classB.cpp:
#include "classB.h"
classB::classB()
{
}
void classB::callFunction()
{
// I should call classA's callback here!
}
The problem is, I can’t include classA.h in classB.h because it will cause some compile issue elsewhere(I can’t solve that). I can’t make classB as classA’s subclass(if I can, I just have to do classA::callBack() instead). So is there a solution to this situation?
UPDATE:that’s what I’ve modified:
class classB
{
public:
classB(classA& pCallBack);
void callFunction();
void (classA::*m_callback)(void);
};
classA::classA()
{
pClassB = new classB(*this);
}
classB::classB(classA& pCallBack)
{
m_callback = pCallBack;
}
I tried to save the pointer, but also failed. It says “assigning from incompatible type”… what’s wrong with it??
Indeed, reciprocally including both headers in each other is a circular dependency, which the compiler can’t resolve. There are different ways to solve this, three of which I describe below.
Using forward declarations
The most straightforward way to break the circular dependency is to use forward declarations. A forward declaration only tells the compiler that a given name denotes a class. That is enough if you only use pointers/references to that type, because in these cases the compiler doesn’t need the full definition of that type. So you can change classA.h like this:
This way the header is not dependent on classB.h anymore. Of course, you need now to
#includethat header in classA.cpp:Introducing an interface
Another way is to introduce a super interface (or in C++, an abstract superclass) to
classA, and letclassBsee only that:callback.h:
classA.h:
classB.h:
classB.cpp:
As you see, this way
classBdoes not depend onclassAin any way. This in fact allows you to later replaceclassAwith any other implementation ofcallback, without touchingclassB‘s definition.Introducing a function pointer
Yet another possibility would be to define / use a function pointer type matching that of
classA::callBack(), and pass only the pointer to the callback function toclassB, rather than the wholeclassAobject. Although, this only works seamlessly withstaticmethods – for nonstatic functions you still need aclassAobject for the call.Update
You are mixing two approaches (passing an object of
classAor passing only a function pointer) in your modified code. Better stick with one at a time. The first approach is simpler, this is how it would look like:The function pointer approach would be more complex for nonstatic member functions, because you needed both the function pointer and an object on which to invoke it. An alternative take on it is shown in @Tadeusz’s answer.