For example there are classes A and B. A uses B's methods and vice versa. So, what is usually done is passing a pointer to an object of the other class in the constructor.
But what if they use each other – how should I pass B to A if B is not yet constructed? Ok, I wrote setter for A and call it after both are created. Now I don't use any B's code in A constructor, but it may change. What should I do then?
class A;
class B;
// A uses B
class A {
B* b;
public:
A() {
// potentially calls b's methods
}
void setB(B* b) { this->b = b; }
}
// B uses A
class B {
A* a;
public:
B(A* a) : a(a) {
// potentially calls a's methods
}
}
int main() {
A a;
B b(&a);
a.setB(&b); // ugly, but no alternative?
// Other classes use a and b
return 0;
}
Either the chicken, or the egg, must come first. One of these objects must be created before the other one.
There are only two ways to cheat:
Declare both objects in global scope and use forward declarations:
extern A a;
extern B b;
A a{&b};
B b{&a};
Note that a still gets constructed before b, so invoking b's methods in a's constructor will be undefined behavior. But merely saving a pointer to the object is fine.
A variation of this is to construct both objects as member of a third object, and basically do the same thing in the object's constructor:
struct C {
A a;
B b;
C() : a{&b}, b{&a} {}
};
Now, instantiating C in automatic or dynamic scope will instantiate both objects, passing each other's address to their respective constructors. But you still can't avoid the fundamental C++ property that only one object gets constructed at a time (in the same execution thread).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With