c++ 成员函数指针
C++中,成员指针是最为复杂的语法结构。但在事件驱动和多线程应用中被广泛用于调用回叫函数。在多线程应用中,每个线程都通过指向成员函数的指针来调用该函数。在这样的应用中,如果不用成员指针,编程是非常困难的。
刚遇到这种语法时也许会让你止步不前。但你会发现,使用恰当的类型定义之后,复杂的语法是可以简化的。本文引导你了解成员函数指针的声明,赋值和调用回叫函数。
成员函数指针的声明
一个成员函数指针包括成员函数的返回类型,后随::操作符类名,指针名和函数的参数。初看上去,语法有点复杂。其实可以把它理解为一个指向原函数的指针,格式是:函数返回类型,类名,::操作符,指针星号,指针名,函数参数。
一个指向外部函数的指针声明为:
void (*pf)(char *, const char *);
void strcpy(char * dest, const char * source);
pf=strcpy;
一个指向类A成员函数的指针声明为:
void (A::*pmf)(char *, const char *);
声明的解释是:pmf是一个指向A成员函数的指针,返回无类型值,函数带有二个参数,参数的类型分别是char * 和 const char *。除了在星号前增加A:: ,与声明外部函数指针的方法一样。
赋值
给成员指针赋值的方法是将函数名通过指针符号&赋予指针名。如下所示:
{
public:
void strcpy(char *, const char *);
void strcat(char *, const char *);
};
pmf = &A::strcpy;
有些老的编译器可以通过没有&号的赋值方式,但标准C++强制要求加上&号。
使用类型定义
可以用类型定义来隐藏复杂的成员指针语法。例如,下面的语句定义了PMA是一个指向A成员函数的指针,函数返回无类型值,函数参数类型为char * 和 const char *:
typedef void(A::*PMA)(char *, const char *);
PMA pmf= &A::strcat; // pmf是PMF类型(类A成员指针)的变量
下文会看到使用类型定义特别有利于声明成员指针数组。
通过成员指针调用成员函数
可以在不必知道函数名的情况下,通过成员指针调用对象的成员函数。例如,函数dispatcher有一个变量pmf,通过它调用类成员函数,不管它调用的是strcpy()函数还是strcat()函数。指向外部原函数的指针和指向类成员函数的指针是有很大区别的。后者必须指向被调函数的宿主对象。因此,除了要有成员指针外,还要有合法对象或对象指针。
现举例做进一步说明。假设A有二个实例,成员函数指针支持多态性。这样在成员指针调用虚成员函数时是动态处理的(即所谓后联编 - 译注)。注意,不可调用构造和析构函数。示例如下:
/**
www.jiedichina.com
*/
A a1, a2;
A *p= &a1; //创建指向A的指针
//创建指向成员的指针并初始化
void (A::*pmf)(char *, const char *) = &A::strcpy;
//要将成员函数绑定到pmf,必须定义呼叫的对象。
//可以用*号引导:
void dispatcher(A a, void (A::*pmf)(char *, const char *))
{
char str[4];
(a.*pmf)(str, “abc”); //将成员函数绑定到pmf
}
//或用A的指针表达方式指向成员指针:
void dispatcher(A * p, void (A::*pmf)(char *, const char *))
{
char str[4]; (p->*pmf)(str, “abc”);
}
//函数的调用方法为:
dispatcher(a, pmf); // .* 方式
dispatcher(&a, pmf); // ->* 方式
高级使用技巧
以上是成员函数的基本知识。现在介绍它的高级使用技巧。
成员指针数组
在下例,声明了一个含有二个成员指针的数组,并分配类的成员函数地址给成员指针:
PMA pmf[2]= {&A::strcpy, &A::strcat};
也就是
void (A::*PMA[2])(char *, const char *)= {&A::strcpy, &A::strcat};
这样的数组在菜单驱动应用中很有用。选择菜单项后,应用将调用相应的回叫函数,如下所示:
int main()
{
MENU_OPTIONS option; char str[4];
//从外部资源读取选项
switch (option)
{
case COPY:
(pa->*pmf[COPY])(str, “abc”);
break;
case CONCAT:
(pa->*pmf[CONCAT])(str, “abc”);
break;
//…
}
}
Const 类型的成员函数
成员指针的类型应该与成员函数类型一致。上面例子中的pmf 可以指向A的任意函数,只要该函数不是const类型。如下所示,如果将touppercase()的地址分配给pmf,将导致编译出错,因为touppercase() 的类型是const。
{
public:
void strpcy(char *, const char *);
void strcat(char *, const char *);
void touppercase(char *, const char*) const;
};
pmf=&A::touppercase; //出错,类型不匹配
//解决的方法是声明一个const类型的成员指针:
void (A::pcmf)(char *, const char *) const;
pcmf=&A::touppercase; // 现在可以了
有些差劲的编译器允许一个非const类型的成员指针指向const类型的成员函数。这在标准C++是不允许的。
https://blog.csdn.net/jiedichina/article/details/7082764
c++ 成员函数指针的更多相关文章
- 为什么 C++ 中成员函数指针是 16 字节?
当我们讨论指针时,通常假设它是一种可以用 void * 指针来表示的东西,在 x86_64 平台下是 8 个字节大小.例如,下面是来自 维基百科中关于 x86_64 的文章 的摘录: Pushes a ...
- C++ 指向成员函数指针问题
成员函数指针与常规指针不同,一个指向成员变量的指针并不指向一个内存位置.通常最清晰的做法是将指向数据成员的指针看作为一个偏移量. class ru_m { public: typedef int (r ...
- [Reprint]C++普通函数指针与成员函数指针实例解析
这篇文章主要介绍了C++普通函数指针与成员函数指针,很重要的知识点,需要的朋友可以参考下 C++的函数指针(function pointer)是通过指向函数的指针间接调用函数.相信很多人对指向一般 ...
- 类成员函数指针 ->*语法剖析
在cocos2d-x中,经常会出现这样的调用,如 ->*,这个是什么意思呢,如下面得这个例子: , 其实这是对类的成员函数指针的调用,在cocos2dx中,这种形式多用于回调函数的调用.如我们经 ...
- C++ 类的成员函数指针 ( function/bind )
这个概念主要用在C++中去实现"委托"的特性. 但现在C++11 中有了 更好用的function/bind 功能.但对于类的成员函数指针的概念我们还是应该掌握的. 类函数指针 就 ...
- C++的类成员和类成员函数指针
类成员函数指针: 用于访问类成员函数,和一般函数指针有区别. 类成员函数处理的是类数据成员,声明类成员函数指针的同时,还要指出具体是哪个类的函数指针才可以.调用时也要通过对象调用. 而对于类的静态成员 ...
- 从汇编看c++成员函数指针(三)
前面的从汇编看c++中成员函数指针(一)和从汇编看c++成员函数指针(二)讨论的要么是单一类,要么是普通的多重继承,没有讨论虚拟继承,下面就来看一看,当引入虚拟继承之后,成员函数指针会有什么变化. 下 ...
- 从汇编看c++成员函数指针(二)
下面先看一段c++源码: #include <cstdio> using namespace std; class X { public: virtual int get1() { ; } ...
- 从汇编看c++中成员函数指针(一)
下面先来看c++的源码: #include <cstdio> using namespace std; class X { public: int get1() { ; } virtual ...
- VB6/VBA中跟踪鼠标移出窗体控件事件(类模块成员函数指针CHooker类应用)
一.关于起因 前几天发了一篇博文,是关于获取VB类模块成员函数指针的内容(http://www.cnblogs.com/alexywt/p/5880993.html):今天我就发一下我的应用实例. V ...
随机推荐
- Maven学习笔记5
Web项目的部署: web部署 配置步骤 生成项目方式不是quickstart,而是webapp. 默认目录结构,需要修改配置. 重新配置project facets和java compiler.并重 ...
- 【Codeforces Round #453 (Div. 2) A】 Visiting a Friend
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 维护最右端的端点就好. [代码] #include <bits/stdc++.h> using namespace st ...
- Spring学习总结(10)——Spring JMS---三种消息监听器
消息监听器MessageListener 在spring整合JMS的应用中我们在定义消息监听器的时候一共可以定义三种类型的消息监听器,分别是MessageListener.SessionAwareMe ...
- SpringMVC,Mybatis,FreeMarker连接mycat示例(一)
首页 > 程序开发 > 软件开发 > Java > 正文 SpringMVC,Mybatis,FreeMarker连接mycat示例(一) 项目结构如图: 首先是各种配置文件, ...
- 洛谷 P2694 接金币
P2694 接金币 题目描述 在二维坐标系里,有N个金币,编号0至N-1.初始时,第i个金币的坐标是(Xi,Yi).所有的金币每秒向下垂直下降一个单位高度,例如有个金币当前坐标是(xf, yf),那么 ...
- ED/EP系列1《简单介绍》
电子存折(ED:ElectronicDeposit)一种为持卡人进行消费.取现等交易而设计的支持个人识别码(PIN)保护的金融IC卡应用. 它支持圈存.圈提.消费和取现等交易. 电子钱包(EP:Ele ...
- 【JavaScript】--JavaScript总结一览无余
对于 北风网李炎恢老师的JavaScript的视频也真的是醉了.视频整体来说结构清晰.内容比較简单.JS是一种灵活,开放的语言,语法规则并没有那么的死板.非常easy让人接受. JS的基础部分跟C#类 ...
- 3lession-python编程规范
今天继续学习python,内容主要就是python编程过程中的一些规范,包括注释.换行等 1.注释 所有的注释都是以#开头,注释可以单独占有一行,也可以放到语句的末尾.因为python没有多行注释,所 ...
- "C:\Program Files\Internet Explorer\iexplore.exe" -extoff 无加载项启动IE 浏览器打开时全屏模式
"C:\Program Files\Internet Explorer\iexplore.exe" -extoff 无加载项启动IE浏览器打开时全屏模式
- 【部分原创】python实现视频内的face swap(换脸)
1.准备工作,按博主的环境为准 Python 3.5 Opencv 3 Tensorflow 1.3.1 Keras 2 cudnn和CUDA,如果你的GPU足够厉害并且支持的话,可以选择安装 那就先 ...