【问题标题】:Will forward-declaration of two classes lead to circular dependency in the constructor?两个类的前向声明会导致构造函数中的循环依赖吗?
【发布时间】:2018-08-10 00:15:24
【问题描述】:

这是允许的吗?我正在尝试确定构造函数中是否存在循环依赖的风险。

头文件:

class B; //forward declaration 

class A
{
public:
    std::unique_ptr<B> cObj;
    std::vector<B*> cList;
    A();
};

class B
{
public:
    B(A& aObj) : aObjLocal(aObj) {};
    void ShareData(int result);
private:
    A& aObjLocal;
};

Cpp 文件:

void B::ShareData(int result)
{
    for (auto& iterator : aObjLocal.cList)
    {
        (*iterator).ShareData(result);
    }
}

A::A()
{
    cObj = std::make_unique<B>(*this); // <- Will this cause circular dependecy 
}

提前感谢您分享知识。

【问题讨论】:

  • 关于循环依赖的事情是你可以简单地测试它是否编译。如果它已编译,则没有循环依赖。那么,你的程序编译了吗?
  • 这很复杂。是的,它的编译。但是,此代码尚未在任何地方使用。它只会在未来被消耗。
  • cObj = std::make_unique&lt;B&gt;(*this); 不应编译为 cObjB * 并且没有从唯一指针到常规指针的隐式转换。
  • @Phil970 ,我的意思是让 B 成为智能指针。我已经更正了代码。感谢您指出。您能否澄清一下这里是否存在循环依赖的情况?

标签: c++ constructor circular-dependency forward-declaration


【解决方案1】:

这里没有出现循环依赖,因为B 不包含A 类型的实际对象,而只是一个引用。这样,*A::cObj 在构造时具有明确定义的大小,并且不依赖于A 的实现细节(如果B 包含实际的A 而不是引用,则会发生循环依赖,内存创建A 所需的值将是无限的)。

让我们看一个小例子(我将aObjLocal公开只是为了能够打印地址):

int main(){                                                                                          
 A a;                                                                                               
 std::cout << "Address of a:                   " << &a << std::endl;                                                                      
 std::cout << "Address of aObjLocal of a.cObj: " << &((*(a.cObj)).aObjLocal) << std::endl;                                                
}  

输出看起来像这样

Address of a:                   0x7ffe68b95f70
Address of aObjLocal of a.cObj: 0x7ffe68b95f70

所以a.cObj 确实包含对a 的正确引用,代码按预期工作(假设此行为是预期行为)。

【讨论】:

  • 太棒了!谢谢你的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 2011-04-08
  • 2012-10-08
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多