C++:类和回调问题
C++ : Class & callbacks issue
这是我的代码和要求:
我有2个A类和B类,它们没有任何继承。我使用 A 类的一个方法来调用 B 类的一个方法。然后,类 B 的方法应回调类 A 的方法之一以执行回调。
部分代码:
A.h类:
#include "classB.h"
class classA
{
public:
classA();
classB *pClassB;
void callClassB();
void callBack();
};
A类.cpp:
#include "classA.h"
classA::classA()
{
pClassB = new classB();
}
void classA::callBack()
{
return;
}
void classA::callClassB()
{
pClassB->callFunction();
}
类B.h:
class classB
{
public:
classB();
void callFunction();
}
B类.cpp:
#include "classB.h"
classB::classB()
{
}
void classB::callFunction()
{
// I should call classA's callback here!
}
问题是,我不能在classB.h中包含classA.h,因为它会在其他地方引起一些编译问题(我无法解决这个问题)。我不能将 B 类作为 A 类的子类(如果可以的话,我只需要做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;
}
我试图保存指针,但也失败了。它说"从不兼容的类型分配"...怎么了??
事实上,相互包含两个标头是一种循环依赖关系,编译器无法解决。有不同的方法可以解决这个问题,我在下面介绍其中三种。
使用前向声明
打破循环依赖关系的最直接方法是使用前向声明。前向声明仅告诉编译器给定名称表示类。如果仅使用该类型的指针/引用,这就足够了,因为在这些情况下,编译器不需要该类型的完整定义。所以你可以像这样改变类A.h:
class classB;
class classA
{
public:
classA();
classB *pClassB;
void callClassB();
void callBack();
};
这样,标头不再依赖于 classB.h。当然,您现在需要在 classA 中#include
该标头.cpp:
#include "classA.h"
#include "classB.h"
...
接口介绍
另一种方法是引入一个超级接口(或者C++,一个抽象的超类)来classA
,classB
只看到:
回调.h:
class callback
{
public:
virtual void callBack() = 0;
};
A.h类:
#include "callback.h"
class classB;
class classA : public callback
{
public:
classA();
classB *pClassB;
void callClassB();
void callBack();
};
类B.h:
#include "callback.h"
class classB
{
callback& m_a;
public:
classB(callback& a);
void callFunction();
};
B类.cpp:
#include "classB.h"
classB::classB(callback& a) : m_a(a) {}
classB::callFunction()
{
m_a.callBack();
}
如您所见,这种方式classB
不以任何方式依赖于classA
。这实际上允许你以后用任何其他callback
实现替换classA
,而不用触及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();
}
对于非静态成员函数,函数指针方法会更复杂,因为您既需要函数指针,也需要调用它的对象。@Tadeusz的回答中显示了另一种看法。
如果你只需要一个回调,那么类 B 不需要知道任何关于类 A 的信息。只需传递回调即可。我将提供提升(C++11)之前)解决方案:
类B.h:
#include <boost/function.hpp>
class classB
{
void callFunction(boost::function<void()> callback);
}
B类.cpp
void classB::callFunction(boost::function<void()> callback)
{
callback();
}
A类.cpp:
#include <boost/bind.hpp>
void classA::callBack()
{
return;
}
void classA::callClassB()
{
pClassB->callFunction(boost::bind(&classA::callBack, this));
}
使用前向声明,例如:
A.h类:
class classB; // forward declaration
class classA
{
public:
classA();
classB *pClassB;
void callClassB();
void callBack();
};
类B.h:
class classA; // forward declaration
class classB
{
public:
classB();
void callFunction(classA& a);
// could store pointer to classA instance here instead
}
只要您只在 classA.h 中使用指向类 B 的引用或指针,这就可以工作,反之亦然。
A类.cpp:
#include "classA.h"
#include "classB.h"
classA::classA()
{
pClassB = new classB(); // could pass 'this' to classB here instead
}
void classA::callBack()
{
return;
}
void classA::callClassB()
{
pClassB->callFunction(*this);
}
B类.cpp:
#include "classB.h"
#include "classA.h"
classB::classB()
{
}
void classB::callFunction(classA& a)
{
a.callback();
}
- 架构决策:返回std::future还是提供回调
- 正在为Xtensa simcall函数编写回调函数
- 如何在C++中使用非静态成员函数作为回调函数
- FLTK:按下哪个按钮 - 将数字传递给按钮的回调 (lambda)
- 德尔福在回调中出现 GUI 问题
- 在定时器回调函数中使用 Sleep() 会导致C++出现问题吗?
- 将非静态函数绑定到回调时出现问题
- C++中嵌套在另一个 LinkedList 中的 LinkedList 整数上的回调函数问题
- 在回调(CPXcutcallbackadd)中添加用户剪切后,如何编写问题公式(CPXwriteprob)
- 在 Python 中扩展的 C++ 类中的 Seg 错误回调问题
- 托管函数在非托管结构(C++、C#)中作为回调函数传递的问题
- C++:类和回调问题
- C++OOP注册回调函数(typedef问题)
- 这个回调有什么问题?
- GLUT回调方法问题
- GLUT回调函数的问题
- 从c++回调到JS的问题
- c++中的一个BST回调函数和函数指针问题
- 回调函数问题
- 窗口事件回调函数C++的问题