C++回调函数、静态函数、成员函数踩过的坑。

明确一点即回调函数需要是静态函数。原因:

  • 普通的C++成员函数都隐含了一个this指针作为参数,这样使得回调函数的参数和成员函数参数个数不匹配。

若不想使用C式函数作为回调函数呢?(破坏封装性)

解决方法

  • 使用static修饰成员函数。static不含this指针。
  • 不用static修饰的成员函数,需要借助中间变量来访问。这个演示的很好。
  • 也可以在回调函数中增加一个变量,类型为该类的类型,作为this指针的传递。

下面讲解一下第二点,我认为比较好用。

class A
{
public:
static void staticmember(){cout<<"static"<<endl;} //static member
void nonstatic(){cout<<"nonstatic"<<endl;} //nonstatic member
virtual void virtualmember(){cout<<"virtual"<<endl;};//virtual member
};
int main()
{
A a;
//static成员函数,取得的是该函数在内存中的实际地址,而且因为static成员是全局的,所以不能用A::限定符
void (*ptrstatic)() = &A::staticmember;
//nonstatic成员函数 取得的是该函数在内存中的实际地址
void (A::*ptrnonstatic)() = &A::nonstatic;
//虚函数取得的是虚函数表中的偏移值,这样可以保证能过指针调用时同样的多态效果
void (A::*ptrvirtual)() = &A::virtualmember;
//函数指针的使用方式
ptrstatic();
(a.*ptrnonstatic)();
(a.*ptrvirtual)();
}

直接用类名引出非静态成员函数,赋值给函数指针:

//nonstatic成员函数 取得的是该函数在内存中的实际地址
void (A::*ptrnonstatic)() = &A::nonstatic;

随后需要运行回调函数的时候,使用一个辅助变量来运行,格式为:(变量名. * 函数指针)(参数)

(a.*ptrnonstatic)();

应用:类中成员函数的函数指针写法

如果在我们的编程过程中:

  1. 需要使用到回调函数。
  2. 回调函数是一个类的成员函数。
  3. 此成员函数不是静态函数,也不适合做静态函数。

我们可以使用:

bool (DoTask::*function)(void *arg);

其中DoTask是一个类名,上面写的就是一个返回值为bool类型,参数为void *类型的函数指针,指向DoTask这个类中的成员函数。

然后调用的时候我们可以:

Dotask d;
//注意ReadData函数不用加括号,要加作用域和地址符
bool (DoTask::*function)(void *arg) = &DoTask::ReadData;
(d.*function)(NULL);

注意点就是赋值给函数指针的时候需要取地址符、加作用域、函数不加括号,直接函数名即可。

调用的时候,用一个实例去调用函数指针即可。

其它

假如我们将函数指针放在一个结构体中:

struct task
{
bool (DoTask::*function)(void *arg);
void *arg;
};

那么我们调用它的时候也是一样的。

struct task t;
t.function = &DoTask::ReadData;
...
DoTask d;
(d.*(t.function))(NULL); //完成调用。

现在看调用这一步。参照上面的:

(d.*function)(NULL)

只不过function现在存在结构体中,替换成从结构体中取出来即可:

function 替换成 t.function

代入即可。

最新文章

  1. Jquery知识点
  2. CentOS7 安装MongoDB 3.0服务器
  3. FORM 提示保存
  4. 安装新版xampp后apache无法启动提示:Apache Service detected with wrong path解决方案
  5. ci 基础知识
  6. 【2012.1.24更新】不要再在网上搜索eclipse的汉化包了!
  7. 负margin新解
  8. swipe方法
  9. 二分查找(Java)
  10. Java 图片处理解决方案:ImageMagick 快速入门
  11. 【Java学习笔记之十五】Java中的static关键字解析
  12. The operation could not be performed because OLE DB provider &quot;SQLNCLI11&quot; for linked server &quot;SDSSDFCC&quot; was unable to begin a distributed transaction.
  13. NeuChar 平台使用及开发教程(一):开始使用 NeuChar
  14. JavaScript入门学习笔记(JSON)
  15. linux 命令 — grep
  16. Confluence 6 通过 SSL 或 HTTPS 运行 - 确定你的证书路径
  17. *jquery操作DOM总结 (原创:最全、最系统、实例展示)
  18. 学习C#(一)
  19. 2010 NEERC Western subregional
  20. Codeforces 894B - Ralph And His Magic Field

热门文章

  1. 怎样理解 MVVM ( Model-View-ViewModel ) ?
  2. ZOOKEEPER进阶
  3. MVC4中去掉浏览器生成的无关代码方法
  4. Laravel save部分字段失效的bug问题解决
  5. vue打包后css背景图片地址找不到
  6. 创建LEANGOO项目
  7. vue滚动+滑动删除标记(移动端)仿qq/微信
  8. kali安装开启ssh &amp; 安装docker
  9. another-redis-desktop-manager
  10. vim 绑定到 source insight 快捷键