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:: ,与声明外部函数指针的方法一样。
赋值
给成员指针赋值的方法是将函数名通过指针符号&赋予指针名。如下所示:
class 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有二个实例,成员函数指针支持多态性。这样在成员指针调用虚成员函数时是动态处理的(即所谓后联编 - 译注)。注意,不可调用构造和析构函数。示例如下:
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};
这样的数组在菜单驱动应用中很有用。选择菜单项后,应用将调用相应的回叫函数,如下所示:
enum MENU_OPTIONS { COPY, CONCAT };
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。
Class A
{
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++是不允许的。
C++成员指针的更多相关文章
- c++_day5_成员指针
1.成员指针实质:特定成员变量在对象实例中的相对地址. 2.类内可以直接初始化静态常量(声明部分).
- C++ Primer 笔记——类成员指针
1.当我们初始化一个成员指针或为成员指针赋值时,该指针并没有指向任何数据.成员指针指定了成员而非成员所属的对象,只有当解引用成员指针时,我们才提供对象信息. 2.和普通的函数指针类似,如果成员存在重载 ...
- C/C++基础----特殊工具和技术 (重载new和delete,RTT,限定作用域的枚举类型,类成员指针,嵌套类,局部类,volatile,链接指示 extern “C”)
重载new和delete 1调用operator new( 或new[])标准库函数分配足够大的.原始的.未命名的内存空间以便存储特定类型的对象 2编译器运行相应地构造函数以构造这些对象,并为其传入初 ...
- C/C++杂记:深入理解数据成员指针、函数成员指针
1. 数据成员指针 对于普通指针变量来说,其值是它所指向的地址,0表示空指针. 而对于数据成员指针变量来说,其值是数据成员所在地址相对于对象起始地址的偏移值,空指针用-1表示.例: 代码示例: str ...
- C++中的类成员指针
写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...
- 【转载】C/C++杂记:深入理解数据成员指针、函数成员指针
原文:C/C++杂记:深入理解数据成员指针.函数成员指针 1. 数据成员指针 对于普通指针变量来说,其值是它所指向的地址,0表示空指针.而对于数据成员指针变量来说,其值是数据成员所在地址相对于对象起始 ...
- 拷贝构造和拷贝赋值、静态成员(static)、成员指针、操作符重载(day06)
十七 拷贝构造和拷贝赋值 浅拷贝和深拷贝 )如果一个类中包含指针形式的成员变量,缺省的拷贝构造函数只是复制了指针变量的本身,而没有复制指针所指向的内容,这种拷贝方式称为浅拷贝. )浅拷贝将导致不同对象 ...
- 成员指针与mem_fn
本文是<functional>系列的第4篇. 成员指针是一个非常具有C++特色的功能.更低级的语言(如C)没有类,也就没有成员的概念:更高级的语言(如Java)没有指针,即使有也不会有成员 ...
- C++ 类成员指针
C++的类成员指针是一种奇葩的指针. 假设现在我们要表示一个三维的点,现在有两种定义方式: struct point1{ int x, y, z; }; struct point2{ int c[3] ...
随机推荐
- 【leetcode刷题笔记】Linked List Cycle
Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using ext ...
- EntityFramework 学习 一 Model Browser
我们已经为School表创建第一个实体数据模型,可视化的EDM设计器不显示所有的实体,而是显示和数据库中对应的表和视图 Model Browser为你提供关于所有对象和函数的信息, Diagrams ...
- codevs1218 疫情控制
疫情控制(blockade.cpp/c/pas)[问题描述]H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点.H 国的首都爆发了一种危害 ...
- APP被应用商店下架了怎么办?
上周五的时候,知乎被各大APP应用商店下架,原因是因为在应用内一些信息不符合相关的规定所以被强制性下架,看起来只是简单的一个应用被下架的事情.但是作为一个推广人员,我第一件事情想到的是,假如我自己公司 ...
- 【海量之道】海量之道之SET模型
本文介绍了set模型. 一 提供海量服务时面对的场景 场景1:如何令黄村机房的TWS机器访问黄村机房的APP服务,避免TWS跨机房调用永丰机房的APP机器? 场景2:DB和Redis如何实现快慢分离, ...
- Twitter的流处理器系统Heron——升级的storm,可以利用mesos来进行资源调度
2011年,Twitter发布了开源的分布式流计算系统Storm.四年后,随着用户数量的急剧增加,Twitter每天要处理的事件已经增加到十亿以上.Storm系统应对如此庞大而复杂多样的流数据变得十分 ...
- JavaUtil_09_通用工具类-01_Hutool
一.重要的官方资料 1. Hutool 官网 2. Hutool 参考文档 3. Hutool API文档
- 实现两个窗口通信方法-postMessage
此方案可解决跨域而且跨Iframe,而且http和https之间的交互 首先来看一下基本的语法 otherWindow.postMessage(message, targetOrigin, [tran ...
- Qt Quick之TableView的使用
本博只是简单的展示TableView的基本使用(TableView.style:TableViewStyle.headerDelegate.rowDelegate.itemDelegate.Table ...
- hdu 3998 Sequence
There is a sequence X (i.e. x[1], x[2], ..., x[n]). We define increasing subsequence of X as x[i1], ...