为什么前向声明和指针(或引用?)可以解决循环依赖?

时间:2015-08-10 06:27:55

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

我知道循环依赖可以通过前向声明和指针解决,如下所示:

A.H

class B;
class A{
public:
    void update(B* b);
    void test(){}
};

A.cpp

#include "A.h"
#include "B.h"
void A::update(B* b){
    b->test();
}

B.h

class A;
class B{
public:
    void update(A* a);
    void test(){}
};

B.cpp

#include "B.h"
#include "A.h"
void B::update(A* a){
    a->test();
}

这样上面的代码可以相互包含编译,但问题是,为什么它可以说是"解决循环依赖"?我不满意" B"仍然存在于A和" A"的源代码中。仍然存在于B的源代码中。至少我认为它应该改变设计模式,以便没有类可以相互包含,例如,使用父类来保存A和B.:

Parent.h

class A;
class B;
class Parent{
    void update(A* a,B* b);
};

Parent.cpp

void Parent::update(A* a,B* b){
    a->test();
    b->test();
}

为什么使用前向声明和指针可以说是"解决循环依赖"甚至源代码仍然相互包含?

2 个答案:

答案 0 :(得分:4)

如果你有A.h的那一行:

using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Project3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            label1.Text = "";
        }
        private void Form1_Load(object sender, EventArgs e)
        {

        }
        private void button1_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            label1.Text = btn.Text;
            int num1 = Int32.Parse(textBox1.Text);
            int num2 = Int32.Parse(textBox2.Text);
            Event t = new Event();
            t.CalculateNow +=new Calculate(t_CalculateNow);
            int finalr = t.Add();
            if (finalr != null)
            {
                label1.Text = "" + finalr;
            }
            else
            {
                label1.Text = "Error!";
            }
        }
    }
}

和B.h与行:

#include "B.h"

A.h和B.h之间存在循环依赖关系。当两个头文件循环相关时,它会在编译时产生问题。您可以使用前向声明来避免它们。

它不排除带有行的A.cpp:

#include "A.h"

B.cpp with lines:

#include "A.h"
#include "B.h"

#include "A.h" #include "B.h" 的实施可能取决于A以及A的定义。
B的实施可能取决于B以及A的定义。

在这种情况下,类是循环相关的,但不是相同意义上两个头文件可以循环相关。

答案 1 :(得分:0)

前向声明指针解析循环依赖项,因为编译器不需要知道要指向的结构或类的内容。它需要知道要插入的某个指针jpegoptim.exe的大小,以及在完全定义了类或结构后具有正确的语义

一个反例是:

sizeof *p == sizeof void *

即使这些结构中的一个或两个都是向前声明的,也必须在结束括号'}'之前知道内容。这种“明显”并非如此。