【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注册,也就是注册指针,有个注册模式似乎与此相关,看后会补充博客。

posted @ 2019-12-26 11:36  LampsAsarum  阅读(1866)  评论(0编辑  收藏  举报