简体   繁体   English

构造相互引用的对象

[英]Constructing objects with mutual references to each other

I've run into a bit of a chicken and the egg scenario.我遇到了一些鸡和蛋的场景。

Say I have these two classes说我有这两个课

class A{
public:
    A(B& );
private:
    B& ref;
};

class B{
public:
    B(A& );
private:
    A& ref;
};

Is there any way for me to initialize them?我有什么方法可以初始化它们吗? Because the fields are references, I have to bind them in the member initializer list so they can never be null.因为这些字段是引用,所以我必须将它们绑定到成员初始化器列表中,这样它们就永远不会为空。 However, I can't make either one of them without the other, so I can't even supply the references.但是,我不能在没有另一个的情况下制作其中一个,所以我什至无法提供参考。

Currently, I have two thoughts.目前,我有两个想法。 The first is that I can switch one of the fields to a raw pointer, that way I can just supply a nullptr and bind it later in a method.第一个是我可以将其中一个字段切换为原始指针,这样我就可以提供一个 nullptr 并稍后在方法中绑定它。 However this weakens my null safety so I don't really want to do that.然而,这削弱了我的零安全性,所以我真的不想这样做。 My second thought was that I could just declare a variable without initializing it, so something like我的第二个想法是我可以只声明一个变量而不初始化它,所以像

A foo;
B bar(foo);
foo(bar);

where I just construct it later.我稍后在哪里构建它。 Unfortunately, this calls a default constructor on the first line, which isn't provided, so this doesn't work.不幸的是,这在第一行调用了一个默认构造函数,没有提供,所以这不起作用。

So I would like some advice on getting my current ideas to work, or if there's a built-in mechanism in C++ for this that I don't know about.所以我想要一些关于让我目前的想法发挥作用的建议,或者如果 C++ 中有一个我不知道的内置机制。

Its a chicken and egg problem.这是鸡和蛋的问题。 You need an A to create a B and you need a B to create an A .你需要一个A来创建一个B ,你需要一个B来创建一个A

However, if you always create an A and a B together, then I would suggest, as already mentioned in a comment, to wrap them in a class.但是,如果您总是一起创建AB ,那么我建议,正如评论中已经提到的,将它们包装在一个类中。 Then you can use the member initializer list:然后你可以使用成员初始化列表:

struct B;

struct A {
    A(B& b) : ref(b) {}
    B& ref;
};

struct B {
    B(A& a) : ref(a) {}
    A& ref;
};

struct AB {
    A a;
    B b;
    AB() : a(b),b(a) {}
};

Using the reference to member b before it has been initialized is fine as long as A only stores the reference and does not read from it or call methods.在成员b被初始化之前使用它的引用是可以的,只要A只存储引用并且不从中读取或调用方法。

However, once they are wrapped in the same class it is kind of pointless to have them store references to each other.但是,一旦将它们包装在同一个类中,让它们存储彼此的引用就毫无意义。

Moreover reference members have certain unpleasant implications (eg no copies).此外,参考成员具有某些不愉快的含义(例如,没有副本)。 Consider if thats what you really like or if perhaps pointers are fine.考虑一下这是否是您真正喜欢的,或者指针是否可以。

If you are trying to create a loop dependency then at least one of the members will need to be a pointer.如果您尝试创建循环依赖项,则至少其中一个成员需要是指针。 But it is otherwise fully possible to have this work by using forward declarations.但是通过使用前向声明完全有可能完成这项工作。

class B;
extern B b;

class A
{
public:
    A(B & b)
        : b(b)
    {
    }

private:
    B & b;
};

class B
{
public:
    B(A & a)
        : a(a)
    {
    }

private:
    A & a;
};

A a(b);
B b(a);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM