Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructing two classes using each other

Tags:

c++

oop

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;
}
like image 636
M. Paul Avatar asked Oct 24 '25 04:10

M. Paul


1 Answers

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:

  1. 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.

  1. 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).

like image 186
Sam Varshavchik Avatar answered Oct 25 '25 19:10

Sam Varshavchik