C++:类和回调问题

Rec*_*Hou 2 c++

这是我的代码和要求:

我有2个A和B类,它们没有任何继承.我使用A类的一个方法来调用B类的一个方法.然后B类的方法应该回调A类的一个方法来执行一个回调.

部分代码:

classA.h:

#include "classB.h"

class classA
{
  public:
  classA();
  classB *pClassB;
  void callClassB();
  void callBack();
};
Run Code Online (Sandbox Code Playgroud)

classA.cpp:

#include "classA.h"
classA::classA()
{
  pClassB = new classB();
}

void classA::callBack()
{
  return;
}

void classA::callClassB()
{
  pClassB->callFunction();
}
Run Code Online (Sandbox Code Playgroud)

classB.h:

class classB
{
  public:
  classB();
  void callFunction();
}
Run Code Online (Sandbox Code Playgroud)

classB.cpp:

#include "classB.h"
classB::classB()
{
}

void classB::callFunction()
{
   // I should call classA's callback here!
}
Run Code Online (Sandbox Code Playgroud)

问题是,我不能在classB.h中包含classA.h,因为它会在其他地方引起一些编译问题(我无法解决).我不能将classB作为classA的子类(如果可以的话,我只需要做classA::callBack()).那么这种情况有解决方案吗?

更新:这是我修改过的:

class classB
{
  public:
  classB(classA& pCallBack);
  void callFunction();
  void (classA::*m_callback)(void);
};

classA::classA()
{
  pClassB = new classB(*this);
}

classB::classB(classA& pCallBack)
{
  m_callback = pCallBack;
}
Run Code Online (Sandbox Code Playgroud)

我试图保存指针,但也失败了.它说"从不兼容的类型分配"......它有什么问题?

Pét*_*rök 7

实际上,相互包含两个标头是循环依赖,编译器无法解析.有不同的方法来解决这个问题,其中三个我在下面描述.

使用前向声明

打破循环依赖的最直接方法是使用前向声明.前向声明只告诉编译器给定的名称表示一个类.如果您只使用指向该类型的指针/引用就足够了,因为在这些情况下,编译器不需要该类型的完整定义.所以你可以像这样更改classA.h:

class classB;

class classA
{
  public:
  classA();
  classB *pClassB;
  void callClassB();
  void callBack();
};
Run Code Online (Sandbox Code Playgroud)

这样,标题不再依赖于classB.h.当然,您现在需要#includeclassA.cpp中使用该标头:

#include "classA.h"
#include "classB.h"
...
Run Code Online (Sandbox Code Playgroud)

介绍一个界面

另一种方法是引入一个超级接口(或在C++中,一个抽象的超类)classA,并且classB只看到:

callback.h:

class callback
{
  public:
  virtual void callBack() = 0;
};
Run Code Online (Sandbox Code Playgroud)

classA.h:

#include "callback.h"

class classB;

class classA : public callback
{
  public:
  classA();
  classB *pClassB;
  void callClassB();
  void callBack();
};
Run Code Online (Sandbox Code Playgroud)

classB.h:

#include "callback.h"

class classB
{
  callback& m_a;
public:
  classB(callback& a);
  void callFunction();
};
Run Code Online (Sandbox Code Playgroud)

classB.cpp:

#include "classB.h"

classB::classB(callback& a) : m_a(a) {}

classB::callFunction()
{
  m_a.callBack();
}
Run Code Online (Sandbox Code Playgroud)

如你所见,这种方式classB不依赖classA于任何方式.这实际上允许您稍后替换classA为任何其他实现callback,而无需触及classB定义.

介绍一个函数指针

另一种可能性是定义/使用与之匹配的函数指针类型classA::callBack(),并仅将指向回调函数的指针传递给classB整个classA对象.虽然,这只能与static方法无缝协作 - 对于非静态函数,您仍然需要一个classA调用对象.

更新

您正在classA修改的代码中混合两种方法(传递一个对象或只传递一个函数指针).最好坚持一次一个.第一种方法更简单,这就是它的样子:

class classA;

class classB
{
  classA& m_a;
public:
  classB(classA& a);
  void callFunction();
};

classB::classB(classA& a) : m_a(a) {}

classB::callFunction()
{
  m_a.callBack();
}
Run Code Online (Sandbox Code Playgroud)

函数指针的方法是对非静态成员函数较为复杂,因为你需要这两个函数指针,并在其上调用它的对象.@ Tadeusz的答案显示了另一种选择.