众所周知,C++的类成员函数不能像普通函数那样用于回调,因为每个成员函数都需要有一个对象实例去调用它。
通常情况下,要实现成员函数作为回调函数,一种常用的方法就是把该成员函数设计为静态成员函数,但这样做有一个缺点,就是会破坏类的结构性,因为静态成员函数只能访问该类的静态成员变量和静态成员函数,不能访问非静态的,要解决这个问题,需要把对象实例的指针或引用做为参数传给它。
在一次偶然的机会下,看到了一种方法可以简单的实现回调非静态成员函数,其原理就是把要调用该成员函数的对象实例赋值给一个变量,然后通过该变量来调用成员函数。把逻辑整理了一下,然后写了一个简单的回调代理类,通过这个类,可以简单的实现非静态函数的回调。
CallbackProxy.h
#ifndef __CALLBACK_PROXY_H__
#define __CALLBACK_PROXY_H__
//Tobject:调用对象的类型,Tparam回调函数参数的类型
template<typename Tobject, typename Tparam>
class CCallbackProxy
{
typedef void (Tobject::*CbFun)(Tparam*);
public:
void Set(Tobject *pInstance, CbFun pFun);
bool Exec(Tparam* pParam);
private:
CbFun pCbFun; //回调函数指针
Tobject* m_pInstance; //调用对象
};
//设置调用对象及其回调函数
template<typename Tobject, typename Tparam>
void CCallbackProxy<Tobject, Tparam>::Set(Tobject *pInstance , CbFun pFun)
{
m_pInstance = pInstance;
pCbFun = pFun;
};
//调用回调函数
template<typename Tobject, typename Tparam>
bool CCallbackProxy<Tobject, Tparam>::Exec(Tparam* pParam)
{
(m_pInstance->*pCbFun)(pParam);
return true;
}
#endif
下面演示下如何使用该类
test.cpp
#include "CallbackProxy.h"
class CTest
{
public:
CTest(int nNum);
void CbPrintSum(int *pnAddNum){printf("The Sum is %d\n", m_nSum+*pnAddNum);};
private:
int m_nSum;
};
int main(int argc, char* argv[])
{
CCallbackProxy<CTest, int> CbProxy;
CTest TestInstance(20);
CbProxy.Set(&TestInstance, &CTest::CbPrintSum);
int nNum = 1000;
CbProxy.Exec(&nNum);
return 0;
}
CTest::CTest(int nNum):
m_nSum(nNum)
{
}
分享到:
相关推荐
在C++中,非静态成员函数不能直接作为回调函数的主要原因在于它们依赖于`this`指针。这意味着每次调用成员函数时,都需要提供一个指向对象的指针。这在很多情况下是不方便的,尤其是在需要将函数作为回调注册到其他...
但是,静态成员函数无法直接访问非静态成员变量和非静态成员函数。若需要访问这些成员,可以通过保存类的实例指针来实现。例如,可以创建一个静态成员变量`static A* pThis`,并在类的构造函数中将其初始化为`this`...
如果是成员函数,需要将其声明为`static`,因为非静态成员函数包含隐含的`this`指针,无法直接用作回调。例如: ```cpp class CMyClass { public: static void MyCallbackFunction(void* userData); }; ``` 2...
这是因为非静态成员函数需要通过`this`指针来访问类的实例,而在回调函数中通常没有这样的上下文信息。 例如,在一个类`CFun`中,我们可以定义一个静态成员函数`StaticFun`作为回调函数: ```cpp class CFun { ...
在这个初级示例中,我们将探讨三种主要的回调实现方式:普通函数回调、静态成员函数回调以及非静态成员函数回调。 ### 1. 普通函数回调 普通函数回调是最基础的形式,它涉及将一个普通的、非成员函数的指针作为...
静态成员函数不含有`this`指针,因此可以被直接作为回调函数调用: ```cpp class TClassB { public: static void Display(); static void Wrapper_To_Call_Display() { TClassB objB; objB.Display(); } }; `...
根据给定文件的信息,本文将深入探讨回调函数的C++封装技术,并重点解析文中提到的两个关键知识点:如何使用静态成员函数调用非静态成员函数以及如何通过函数分发进行进一步处理。 ### 一、静态成员函数调用非静态...
这样的特性使得静态成员函数成为一个可作为回调函数(callback function)使用的候选者,这在处理与C-based X Window系统相关的事件处理函数时尤其有用。通过静态成员函数的回调特性,可以实现C++代码与C-based X ...
- 静态成员函数不能访问非静态成员变量和非静态成员函数。 - 不能将静态成员函数定义为虚函数。 2. **取地址操作** - 静态成员函数的地址类型是非成员函数指针。 - 这种特性使得静态成员函数可以用作回调函数,...
这里的`ptrnonstatic`是一个指向`A`类的非静态成员函数`nonstatic`的指针,需要通过对象实例来调用,如`a.*ptrnonstatic()`。 3. **虚函数**: 虚函数在派生类中可以被重写,因此其函数指针存储的是虚函数表...
在C++中,如果想要将类成员函数作为回调函数使用,通常需要将其转换为静态函数或者使用lambda表达式,因为非静态成员函数会隐含地接收一个`this`指针,而回调函数通常只接受函数指针。 例如: ```cpp class ...
要将非静态成员函数作为回调函数,需要额外的步骤。一种方法是使用辅助函数和结构体封装成员函数和对象实例。 ```cpp class MyClass { public: void memberCallback(int data) { printf("Member Callback ...
而静态成员函数不具备所属类的实例上下文,因此它们不能访问非静态成员变量,但它们可以直接通过类名调用,无需对象实例,这使得它们适合作为回调函数。 1. 静态成员函数的特点: - 不需要类的实例就能被调用。 -...
CALLBACK 函数可以将一个 C 函数直接作为回调函数,但是如果试图直接使用 C++ 的成员函数作为回调函数将发生错误。 本资源摘要信息涵盖了 C++ 语言的多个重要知识点,旨在帮助读者快速了解 C++ 语言的基本概念和...
回调函数还可以是全局函数或静态成员函数,这取决于你的需求和设计。在提供的文件中,如`回调函数.txt`和`回调函数1.txt`,可能包含了更多关于如何定义和使用回调函数的详细示例和注意事项。 最后,`C++常见类型...
静态成员函数没有隐含的this指针,无法访问非静态成员。此外,static还可以用于局部变量,使得它在函数调用间保持其状态。 10. 模板:模板是C++的泛型编程工具,可以用于创建泛型函数和泛型类。函数模板允许我们...
- 可以定义指向函数的指针,如`int (*ptr)(int, int)`,这种指针可以作为其他函数的参数或返回值,实现回调或策略模式。 8. **匿名函数(Lambda表达式)**: - C++11引入的特性,允许创建无名函数,如`auto add =...
C++类的成员函数有三种类型:静态成员函数、非静态成员函数和虚拟成员函数,它们的指针获取方式有所不同。 首先,静态成员函数不与类的任何特定实例相关联,而是属于类本身。它们可以被视为全局函数,只是被类封装...
##### 4.4 在 C++ 中实现非静态成员函数作为回调函数 非静态成员函数作为回调函数需要使用一些技巧,例如通过包装器函数或者使用`std::function`等工具: ```cpp class MyClass { public: int compare(const void...