c++循环依赖:构造函数应该是什么样子?



我阅读了很多循环依赖主题,但它们似乎都与声明有关。我感兴趣的是如何构建相互依赖的对象,以及我的方法是否存在潜在的缺陷。考虑这个简单的例子:

#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;
}

我可以做些什么来避免B中的A*指针?

理想情况下,我想有一个引用,但如果我将B的构造函数更改为B(string name, A& a),然后将push_back更改为bs.bush_back(B("First", *this));,我会得到一个错误:non-static reference member 'A& B::myA', can't use default assignment operator。参见修改后的示例

据我所知,编译器合成的operator=不适合这里。正确的operator=是什么样的?还是我走错方向了?

当您在标准容器中使用类型时,如vector,类型需要是CopyConstructibleAssignable。如果你的类型有指针成员,那么它们可以很好地与隐式定义的复制赋值操作符一起工作,但这不是引用成员的情况,因为引用不能被反弹。

如果你想让你的类型在容器中工作,坚持使用指针成员要简单得多。您是否可以定义在特定情况下有意义的复制赋值操作符并不明显,通常情况下是没有意义的。

即使是用户定义的赋值操作符也不能在那里使用引用,因为引用一旦初始化就不能被反弹。这里使用指针是最简单的方法。

在这种情况下(在这种情况下只有),您可以考虑将B作为模板。

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;
};

最新更新