【C++填坑】类的循环引用

最近遇到一个问题,类的循环引用。就是class A定义了class B的对象,class B中也定义了class A的对象。

错误的构造方式:采用直接new的方式,就会产生死循环的问题

//A.h
class B;
class A
{
public:
    A();
    ~A();
private:
    B* b;
};

//A.cpp
#include "A.h"
#include "B.h"

A::A()
{
    b = new B();
}

A::~A()
{
    delete b;
    b = nullptr;
}
//B.h
class A;
class B
{
public:
    B();
    ~B();
private:
    A* a;
};

//B.cpp
#include "B.h"
#include "A.h"

B::B()
{
    a = new A();
}

B::~B()
{
    delete a;
    a = nullptr;
}

讲真的,这样子写一看就知道有问题。但麻烦的是你还不知道怎么去改它。

下面来说说,这个问题如何优雅的解决。

正确的构造方式:使用类似于注册的方式去构造

//A.h
class B;
class A
{
public:
    A();
    ~A();
private:
    B * b;
}; 

//A.cpp
#include "a.h"
#include "b.h"

A::A()
{
    b = new B;
    b->setA(this);//划重点,类似于注册的方式去构造类B里的a
}

A::~A()
{
    delete b;
    b = nullptr;
}
//B.h
class A;
class B
{
public:
    B();//划重点,并不需要实现
    ~B();
    void setA(A * x);
private:
    A * a;
};

//B.cpp
#include "b.h"
#include "a.h"

void B::setA(A * x)
{
    a = x;
}

以上就是解决文件之间循环引用问题的方法。下面加大难度,三个文件之间的循环引用问题。

例子:class A中需要B的指针,class B中需要A的指针和C的指针,class C中需要B的指针。

解决的代码如下:

//A.h
class B;
class A
{
private:
    B* b;
public:
    A();
    ~A();
};

//A.cpp
#include "A.h"
#include "B.h"

A::A()
{
    b = new B;
    b->setA(this);
}

A::~A()
{
    delete b;
}
//B.h
class A;
class C;
class B
{
private:
    A* a;
    C* c;
public:
    B();
    void setA(A* x);
    void doSomething();
    void doSomething2();
};

//B.cpp
#include "B.h"
#include "A.h"
#include "C.h"

B::B()
{
    c = new C;
    c->setB(this);
}

void B::setA(A* x)
{
    a = x;
}
//C.h
class B;

class C
{
public:
    B* b;
    void setB(B* y);
};

//C.cpp
#include "C.h"

void C::setB(B* y)
{
    b = y;
}

至此,三个文件的循环引用问题解决了。当然上述代码没有那么完整,如果跑不通,可以留言。

代码中的set函数好像也可以改成register注册,也就是注册指针,有个注册模式似乎与此相关,看后会补充博客。

原文地址:https://www.cnblogs.com/LampsAsarum/p/12101181.html

时间: 2024-10-04 18:31:41

【C++填坑】类的循环引用的相关文章

深入学习c++--智能指针(二) weak_ptr(打破shared_ptr循环引用)

1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 每添加一次引用 就+1,减少一次引用,就-1:做到指针进行共享 3. unique_ptr: 一个指针同时只能有一个使用者使用 4. weaked_ptr: 与shared_ptr搭配使用 1.1 weak_ptr 参考:https://zh.cppreference.com/w/cpp/memory/weak_ptr std::weak_ptr 是一种智能指针,它对被 std::sha

IOS中解决ARC类实例间循环引用(Swfit)

原创Blog,转载请注明出处 http://blog.csdn.net/column/details/swfitexperience.html 备注:本文代码和图片主要来自于官方文档 不熟悉ARC的同学可以看看前一篇关于ARC的简述,这个是我的Swfit教程专栏 http://blog.csdn.net/column/details/swift-hwc.html 一.几个用到的关键概念 弱引用(weak):不会增加自动引用计数,必须为可选类型变量,因为弱引用在引用计数为0的时候,会自动赋为nil

shell中while循环引用ssh命令的坑

原理shell代码如下: #!/bin/sh cat ../androidsrc | while read line do         ip=$(echo $line | awk '{print $1}')         srcdir=$(echo $line | awk '{print $2}')         destdir=$(echo $line | awk '{print $3}')         user=$(echo $line | awk '{print $4}')  

EF实体类,设置导航属性,导致序列化时出现"循环引用"错误,及序列化时间格式解决方案

三个实体类,学生类(Student),班级类(StudentClass),年级类(Grade) 学生类与班级类为多对一的关系,班级表的主键为学生表的外键,年级表的主键为学生表的外键 public class Student { [Column("StudentId")] public int Id { get; set; } [Required] [StringLength(200)] public string _Name { get; set; } public int _Sex

踩坑(Running)填坑(ZSSURE):DevExpress的XtraTabControl、Telerik的OpenAccessContext以及StarUML

题记: 今天好友在朋友圈分享了一篇有深度的好文"请鼓励你的孩子做个幸福普通人",文章略显长,细细品读下来感触颇多.加之最近天天看着小外甥大睿睿的一步步的成长,已渐渐远离年轻稚嫩.走向成熟稳重的我对学习有了新的认识,回想起自己的成长过程,经验和技能并非是父母手把手教导的,反而是他们给我营造的"自由.开放.甚至略显放纵"的环境.他们以身作则的行动,让我从中体会.感悟出了所有的点点滴滴. 说到现在从事的软件研发工作,想想同学中毕业鲜有留下来做技术的(姑且认为IT民工也属于

Spring 循环引用 ——理解singleton与prototype初始化的区别

所谓的循环引用,就是A依赖B,B又依赖A,A与B两个对象相互持有.像下面这种情况: class A { B b; public A(B b) { this.b=b; } } class B { A a; public B(A a ) { this.a=a; } } 我们知道spring在获取对象或者在加载的时候,触发依赖注入.例如触发A对象的依赖注入,发现需要B对象,而此时B还没有初始化,就去实例化B对象,而又需要A对象,这样就进入了一种死循环状态,有点像操作系统里面的死锁.似乎这种情况发生了,

前端系列——jquery前端国际化解决方案“填坑日记”

前言:最近,新的平台还没有开发完成,原来的老项目又提出了新的需求:系统国际化.如果是前后端完全分离的开发模式,要做国际化,真的太简单了,有现成的解决方案,基于Node构建的时下热门的任何一种技术选型都有成熟的方案,比如: vue + vue-i18n angular + angular-translate react + react-intl 但现在的情况是老的项目并没有使用这类架构.说起国际化,博主几年前就做过,在MVC里面实现国际化有通用的解决方案,主要就是通过资源文件的方式定义多语言.最初

Android Tips – 填坑手册

出于: androidChina   http://www.androidchina.net/3595.html 学习 Android 至今,大大小小的坑没少踩,庆幸的是,在强大的搜索引擎与无私奉献的人们的帮助下,我遇到的坑都顺利地被填平了. 为了便于日后遇到同样的问题时,能免于再次搜索带来的麻烦,我养成了收藏书签的习惯,随着书签(Tips)的日积月累,我想,是时候该有这个项目了. 如果你是个 Android 新人,那么我希望这份列表,可以成为你踩到坑时的不完全手册. 当然,这份列表一定会有遗漏

和block循环引用说再见

to be block? or to be delegate? 这是一个钻石恒久远的问题.个人在编码中暂时没有发现两者不能通用的地方,习惯上更偏向于block,没有什么很深刻的原因,只是认为block回调写起来更便捷,直接在上下文中写block回调使得代码结构更清晰,可读性更强.而delegate还需要申明protocol接口,设置代理对象,回调方法与上下文环境不能很好契合,维护起来没有block方便.另外初学者很容易会被忘记设置代理对象坑- 然而惯用block是有代价的,最大的风险就是循环引用