开发者

C++ circular dependency: What should the constructor look like?

开发者 https://www.devze.com 2023-03-20 07:02 出处:网络
I read through a lot of circular dependency topics but all of them seem to be concerned with the declaration. I am interested how to construct the mutually depended objects and if there are potential

I read through a lot of circular dependency topics but all of them seem to be concerned with the declaration. I am interested how to construct the mutually depended objects and if there are potential pitfalls with my approach. Consider this simple example:

#include <iostream>
#include <vector>
using namespace std;

class A; //Forward declaration

class B{
    public:
        B(string name, A* a):myA(a), name(name){
            cout << "Works with pointer" << endl;
        };
    private:
        A* myA;
        string name;

};

class A{
    public:
        A(){
            cout << "Constructing A" << endl;
            if(bs.empty()) cout << "Vector is empty" << endl;
            bs.push_back(B("First", this));
            cout << "Array has " << bs.size() << " elements." << endl;
        };
    private:
        std::vector<B> bs;
};


int main() {
    cout << "Start" << endl;
    A开发者_如何转开发 a;
    cout << "Ok." << endl;
    return 0;
}

Is there anything that I could do to avoid the A* pointer in B?

Ideally I would like to have a reference, but if I change the constructor of B to B(string name, A& a) and then change the push_back to bs.bush_back(B("First", *this)); I get an error: non-static reference member 'A& B::myA', can't use default assignment operator. See the modified example

As far as I can tell the operator= that is synthesized by the compiler does not fit here. How would the proper operator= look like? Or am I going the wrong direction all together?


When you use a type in a standard container, like vector the type needs to be CopyConstructible and Assignable. If your type has pointer members then these will work fine with an implicitly defined copy assignment operator but this is not the case with reference members as references can't be rebound.

If you want your type to work in a container it is much simpler to stick with pointer members. It's not obvious whether you can define a copy assignment operator that makes sense in your particular case, in general it isn't.


You couldn't use a reference there even with a user-defined assignment-operator, because references cannot be rebound once they are initialized. Using a pointer here is the simplest approach.


In this case (and only in this case), you could consider making B a template..

template <typename SomeA>
class B{
    public:
        B(string name, SomeA& a):myA(a), name(name){
            cout << "Works with reference" << endl;
        };
    private:
        boost::optional<SomeA&> myA;
        string name;
};

class A{
    public:
        A(){
            cout << "Constructing A" << endl;
            if(bs.empty()) cout << "Vector is empty" << endl;
            bs.push_back(B<A>("First", *this));
            cout << "Array has " << bs.size() << " elements." << endl;
        };
    private:
        std::vector<B<A> > bs;
};

This suggestion is purely without any context...

0

精彩评论

暂无评论...
验证码 换一张
取 消