回调函数必须要用static的原因
在之前的一篇回调函数简单例子中就写了一个简单的回调小例子,这里补充一下。
一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。
为了实现回调,我们必须把this指针给转换掉!可为了在该函数中可以直接操作该类中的成员,我们必须保留this指针!所以这是矛盾的。
在类封装回调函数:
a.回调函数只能是全局的或是静态的。
b.全局函数会破坏类的封装性,故不予采用。
c.静态函数只能访问类的静态成员,不能访问类中非静态成员
让静态函数访问类的非静态成员的方法:
在消息回调的函数参数中传递一个该类的指针即可,就像类中创建一个多线程的回调一样.将类的指针传递给该回调函数,然后用该指针调用类的非静态成员函数和指针.或者用一个类的全局指针数组,保存每一个创建出来的类的this指针,用全局指针去调用。如下:
class A()
回调函数中访问非静态成员
由于回调函数往往有固定定义,并不接受 A * pThis 参数
如:CALLBACK MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
【解决方案1】:本方案当遇到有多个类实例对象时会有问题。原因是pThis指针只能指向一个对象。
class A()
{
static void a(); //静态回调函数
void b(); //非静态函数
static A * pThis; //静态对象指针
}
A * A::pThis=NULL; //这句话必须要在cpp一开始就写,不然编译会报无法解析的外部符号的错。
A::A() //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象
{
pThis=this;
}
void A::a()
{
if (pThis==NULL) return;
pThis->b(); //回调函数中调用非静态函数
}
【解决方案2】:本方案解决多个类实例对象时方案1的问题。用映射表存所有对象地址,每个对象保存自己的ID号。
typedef CMap<UINT,UINT,A*,A*> CAMap;
class A()
{
static void a(); //静态回调函数
void b(); //非静态函数
int m_ID; //本对象在列表中的ID号
static int m_SID; //静态当前对象ID (需要时,将m_ID赋值给m_SID以起到调用本对象函数的功能)
static CAMap m_Map; //静态对象映射表
}
CAMap A::m_Map;
int A::m_SID=0;
A::A() //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象
{
if(m_Map.IsEmpty())
{
m_ID=1;
}
else
{
m_ID=m_Map.GetCount()+1;
}
m_Map.SetAt( m_ID, this );
}
void A::a()
{
if (m_Map.IsEmpty()) return;
A * pThis=NULL;
if(m_Map.Lookup(m_SID,pThis))
{
pThis->b(); //回调函数中调用非静态函数
};
}
原文连接:https://blog.csdn.net/u012072012/article/details/45537387
回调函数必须要用static的原因相关推荐
- lwIP 细节之三:TCP 回调函数是何时调用的
使用 lwIP 协议栈进行 TCP 裸机编程,其本质就是编写协议栈指定的各种回调函数.将你的应用逻辑封装成函数,注册到协议栈,在适当的时候,由协议栈自动调用,所以称为回调. 注:除非特别说明,以下内容 ...
- Java对C语言Dll的加载 和 回调函数的使用
C语言HWPuSDK.h文件: #ifndef _HW_PU_SDK_H_ #define _HW_PU_SDK_H_#pragma pack(push,4)#ifdef _WIN32// for w ...
- C++回调函数(callback)的使用
什么是回调函数(callback) 模块A有一个函数foo,它向模块B传递foo的地址,然后在B里面发生某种事件(event)时,通过从A里面传递过来的foo的地址调用foo,通知A发生了什 ...
- jQuery $.post()返回类型为json时不进入回调函数的原因及解决方法
jQuery $.post()返回类型为json时不进入回调函数的原因及解决方法 参考文章: (1)jQuery $.post()返回类型为json时不进入回调函数的原因及解决方法 (2)https: ...
- c++类的成员函数作回调函数为啥要声明为static的
简单说明 C++的类成员函数不能像普通函数那样用于回调,因为每个成员函数都需要有一个对象实例去调用它. 把成员函数作为回调函数,可以把该成员函数声明为静态成员函数,但这样做有一个缺点,就是会破坏类的结 ...
- C++ 实现把非静态成员函数作为回调函数(非static)
众所周知,C++的类成员函数不能像普通函数那样用于回调,因为每个成员函数都需要有一个对象实例去调用它. 通常情况下,要实现成员函数作为回调函数,一种常用的方法就是把该成员函数设计为静态成员函数,但这样 ...
- 李老三借钱吃麻辣烫但不耽误回家喂熊猫,原因竟是他会回调函数!!
大家好,我是永远吃不饱的小胖鱼. 这两天在写<动手学ROS2>教程的时候,一会冒出来一个回调函数. 因为担心未来的读者们被回调函数绕晕,小鱼今天就特意把回调函数拎出来说一说. 顺便说一说什 ...
- 回调函数 线程_从0实现基于Linux socket聊天室-多线程服务器一个很隐晦的错误-2...
根据 <0 基于socket和pthread实现多线程服务器模型>所述,server创建子线程的时候用的是以下代码: pconnsocke = (int *) malloc(sizeof( ...
- QT信号与槽——观察者模式——回调函数
QT信号与槽--观察者模式--回调函数 1.QT信号与槽机制 1.1信号本质 信号是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时候 Qt 对应的窗口类会发出某个信号.比如 ...
最新文章
- RSTP的根保护功能
- vue项目-点击添加或者修改按钮浏览器的屏幕变黑,再次点击屏幕之后浏览器恢复正常(火狐浏览器、ChromeCoreLauncher双核浏览器)
- 搜索,然后学习:两阶段的无监督文本生成
- 文件与文件夹课后作业
- 为啥一到年底腾讯市值就大涨??????
- Visual Studio Code 快捷键的设置
- 高可用性、负载均衡的mysql集群解决方案
- php的转义字符quot;反斜杠quot;是,php如何去除转义字符中的反斜杠
- Matplotlib——基本用法
- 导致页面顶部空白一行解决方法
- Galaxy Fold上市时间推延 屏幕瑕疵是主因
- 网络流 增广路 入门很好的文章
- 在线文件管理系统 下载地址
- 05 Confluent_Kafka权威指南 第五章: kafka内部实现原理
- 北大计算机前辈徐,九年中获得国家最高科学技术奖的八位北大人
- LibPcap丢包问题
- uniapp:轮播里如何加入视频
- eureka client无法启动,java.lang.IllegalStateException: Failed to introspect Class
- 淘宝特价版将接入微信 腾讯会松口吗?
- NightWatchJS
热门文章
- 【GO语言学习】使用GO语言输出Emoji表情
- CRC算法 个人学习笔记 直接法、查表法注意点
- 基于JAVA酒店后厨供应商订单合并系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
- 续章一区百战金牌指挥·盟重土城
- php.ini development,php.ini-development、php.ini-production、php.ini-dist,php.ini-
- create connection SQLException, url: jdbc:mysql://127.0.0.1:3306/xxxx, errorCode 0, state 08001
- 远程计算机后无法正常播放声音,求大神远程电脑修声音,放电视都没声音,但QQ音乐有声音...
- 能够背熟对你的学习很有好处的
- 运维学习 之 Ngnix配置(详细版)
- Android开源框架集合分享-图像加载