如何创建通过前向声明实现循环引用的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
相关产品推荐
相关产品推荐

