If youāre defining a class, but only declaring its member functions, then you can easily add a pointer to a different class. You donāt need to know the structure of a class to be able to hold a pointer to it - itās only when you try to dereference it, or use it to call a member function of that class, that you find a problem.
So, the solution is always to separate the implementation of your functions (specifically any that make use of the pointer) from the class definition.
you obviously know your stuff and so i apologise if the rest of this sounds really elementary and childish! but examples are fun!
For example, in my class I know that i need to make use of a gwargleā¦ i even know that a particular function will take/return a gwargleā¦ but right now i donāt know what a gwargle is, and thatās okay because i donāt yet know what those functions will try to do with it. As long as i know that a gwargle exists (forward declaration) and i donāt try to do anything with it, iām okay. The same goes for the gwargleā¦ he is expecting to have to do something with me at some pointā¦ he knows heās got to bear me in mind, but until he goes off to compile his plans, he doesnāt need to know what i actually am. And by the time heās got back, heāll have been given a blueprint showing exactly what he needs to know about me. Heck, iāve just started learning my āgwargleā functions and iāve got here a gwargle schematic so i know which bits do what.
So a āsimpleā solution is to make sure that both classes have their classes defined each in a separate header, each keeping their member function definitions in an external implementation file. The class definitions in the headers are each preceded with a forward declaration of the other, and both implementation files include both headers.
Hereās another simplistic example. [Donāt worry about reading all the code, the important bits are commented and obviousā¦]
Most basic example, with obvious errors:
class A
{
public:
int a;
B* b_ptr; // <--- first error
void f()
{
b_ptr->b = a;
}
};
class B
{
public:
int b;
A* a_ptr;
void f()
{
a_ptr->a = b;
}
};
Here, class A gives an error, trying to make a pointer to a āBā (which the compiler does not yet know about)ā¦ a forward declaration of class B enables the compiler to know enough to allow a pointer to existā¦
class B; // forward declaration...
class A
{
public:
int a;
B* b_ptr; // <--- this is okay now...
void f()
{
b_ptr->b = a; // <--- but THIS is not okay
}
};
class B
{
public:
int b;
A* a_ptr;
void f()
{
a_ptr->a = b;
}
};
ā¦ but now the key problem is that the compiler still doesnāt know how to use the pointer- it certainly doesnāt know that there is a ābā int member in this āBā class type.
So we take the function definition outside, away from the class definition, leaving just a declarationā¦
class B; // forward declaration...
class A
{
public:
int a;
B* b_ptr;
void f(); // <-- the definition would be in A.cpp
};
class B
{
public:
int b;
A* a_ptr;
void f()
{
a_ptr->a = b;
}
};
Everything else in this example is now fine. Of course, we can take it further by putting B into its own file.
// A.h
//----------------------
class B; // forward declaration...
class A
{
public:
int a;
B* b_ptr;
void f(); // <-- the definition would be in A.cpp
};
// B.h
//----------------------
class A; // forward declaration...
class B
{
public:
int b;
A* a_ptr;
void f(); // <-- the definition would be in B.cpp
};
// A.cpp
//----------------------
void A::f()
{
b_ptr->b = a;
}
// B.cpp
//----------------------
void B::f()
{
a_ptr->a = b;
}