You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建通过前向声明实现循环引用的C++类实例?

如何创建循环引用的C++类实例

你给出的代码存在核心矛盾:两个类的构造函数都必须接收对方的引用才能初始化,但C++中引用必须绑定到已存在的对象,这就陷入了“先构造哪个”的死循环——创建class_a需要已存在的class_b,反之亦然。要解决这个问题,必须调整类的设计,以下是几种可行方案:

方案1:将引用改为指针(最常用)

指针允许延迟赋值,我们可以先创建其中一个对象,再构造另一个并补全指针关联:

class class_a;
class class_b;

class class_a {
public:
    // 添加无参构造,指针初始化为空
    class_a() : ptr_to_b(nullptr) {}
    // 保留接收指针的构造函数
    class_a(class_b* arg) : ptr_to_b(arg) {}
    class_b* ptr_to_b;
};

class class_b {
public:
    class_b() : ptr_to_a(nullptr) {}
    class_b(class_a* arg) : ptr_to_a(arg) {}
    class_a* ptr_to_a;
};

int main() {
    class_a a;
    class_b b(&a);
    a.ptr_to_b = &b; // 补全a的指针引用

    // 此时a和b互相指向对方,完成循环引用
    return 0;
}

方案2:用std::reference_wrapper实现可修改的“引用”

如果坚持要类似引用的语义,可借助std::reference_wrapper实现可重新绑定的间接层,绕开原生引用不可修改的限制:

#include <functional>

class class_a;
class class_b;

class class_a {
public:
    // 默认构造,绑定到临时占位对象(仅为初始化,后续会替换)
    class_a() : ref_to_b(std::ref(*static_cast<class_b*>(nullptr))) {}
    class_a(class_b& arg) : ref_to_b(std::ref(arg)) {}
    std::reference_wrapper<class_b> ref_to_b;
};

class class_b {
public:
    class_b(class_a& arg) : ref_to_a(arg) {}
    class_a& ref_to_a;
};

int main() {
    class_a a;
    class_b b(a);
    a.ref_to_b = std::ref(b); // 修改wrapper的绑定对象

    // 此时a和b互相引用
    return 0;
}

方案3:使用全局对象(不推荐)

利用全局对象在main函数前初始化的特性,可让两个全局对象互相引用,但注意:同一编译单元内全局对象的初始化顺序是从上到下的,跨编译单元则不确定,容易引发未定义行为:

class class_a;
class class_b;

class class_a {
public:
    class_a(class_b& arg) : ref_to_b(arg) {}
    class_b& ref_to_b;
};

class class_b {
public:
    class_b(class_a& arg) : ref_to_a(arg) {}
    class_a& ref_to_a;
};

// 先声明b的原型,再定义a,最后定义b
extern class_b b;
class_a a(b);
class_b b(a);

int main() {
    // 此时a和b已完成循环引用
    return 0;
}

内容的提问来源于stack exchange,提问作者Xeenych Xeenych

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:55:14