Michał Barańczyk
Michał Barańczyk

Reputation: 13

C++ Cyclic pointer injection in constructor

I've read a lot of circular dependecies topics, but I couldn't find the one solving my problem. I have two classes containing pointers to each other:

class B;

class A
{
public:
    A(B* _b, int _c): b(_b), c(_c) {}
    B* b;
    int c;
};

class B
{
public:
    B(A* _a, int _d): a(_a), d(_d) {}
    A* a;
    int d;
};

The problem is that in the following code:

class C
{ 
public:
    A* a_ptr;
    B* b_ptr;
    C() 
    {
        a_ptr = new A(b_ptr, 3);
        b_ptr = new B(a_ptr, 2);
        qDebug() << a_ptr->c;
        qDebug() << b_ptr->d;
        qDebug() << a_ptr->b->d;
        qDebug() << b_ptr->a->c;
    }
}

last two lines are crashing application. I understand the problem and the reason of crashes. I could write setters for members and invoke them AFTER creating objects, so the pointers will be valid. However, I want the objects to be complete after invoking contructors, without invoking any other methods.

So... I was wondering if there is any way to inject (cyclic) pointers in constructors?

Upvotes: 1

Views: 215

Answers (1)

Synxis
Synxis

Reputation: 9388

You can make one contructor complete the initialization of the other object:

B(A* a_ptr) : a(a_ptr)
{
    if(a)
        a->b = this;
}

And same for A(). Thus, you can create them like the following:

a_ptr = new A(b_ptr, 3); // b_ptr was initialized to 0
b_ptr = new B(a_ptr, 2); // b_ptr->a = a_ptr
                         // b_ptr->a->b = b_ptr (ie, a_ptr->b = b_ptr)

Edit: As stated in the comment, this is not scalable if you have a lot of classes. However, in the general case you will have to initialize cyclic dependencies outside of constructors, and secondly you shouldn't have a a lot of classes that cyclicly depends on each other (if it is the case, maybe you can rearrange your code...).

Upvotes: 2

Related Questions