C++类成员指针的意义

C++中,成员指针是最为复杂的语法结构。但在事件驱动和多线程应用中被广泛用于调用回叫函数。在多线程应用中,每个线程都通过指向成员函数的指针来调用该函数。在这样的应用中,如果不用成员指针,编程是非常困难的。

1.类成员变量指针

C++中类成员变量指针其实就是一个相对于类对象地址的偏移量。《C++必知必会》的条款15讲述了这一说法:“与常规指针不同,一个指向成员变量的指针并不指向一个内存位置。它指向的是一个类的特定成员,而不是指向一个特定对象里的特定成员。通常最清晰的做法是将指向数据成员的指针看作为一个偏移量。......。这个偏移量告诉你,一个特定成员的位置距离对象的起点有多少个字节。”具体用法如下:

<pre name="code" class="cpp">class A
{
public: 
A(int b):a(b){}
....
public:
    int a;
};
int main()
{
A m(10);
int (A::*p)=&(A.a);//注意,这里是将A.a的"地址"赋值给p,本质不是哦,看下面程序
cout<<"p="<<p<<",a="<<a<<",m.*p="<<m.*p<<endl;//输出p=1,而不是一个地址哦,a=10,m.*p=10
m.*p=11;
cout<<"p="<<p<<",a="<<a<<",m.*p="<<m.*p<<endl;//p=1,a=11,m.*p=11
A *s=&m;
s->*p=12;cout<<"p="<<p<<",a="<<a<<",s->*p="<<s->*p<<endl;//p=1,a=12,s->*p=12
}




从上面的代码可以看出,p不是一个地址,而是一个偏移量,因此必须要提供相对于哪个地址偏移,也就是程序中m.*p,对象m提供了起始地址(对象的存储起始地址),然后加上偏移量p,就定位到了p的成员变量a;或者是通过指向对象m的指针s提供起始地址。

【注】一定不要将引用成员指针赋值对象搞错,int (A::*p)=&(A.a);是类A,而不是对象!

2.类成员函数指针

一个成员函数指针包括成员函数的返回类型、::操作符、类名、指针名和函数的参数。初看上去,语法有点复杂。其实可以把它理解为一个指向原函数的指针,格式是:函数返回类型+类名+::操作符+指针星号+指针名+函数参数,下面用代码说明:

一个指向外部函数的指针声明为:

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;//<strong>注意是类的成员函数名,而不是对象!</strong>
有些老的编译器可以通过没有&号的赋值方式,但标准C++强制要求加上&号

也可以通过类型定义的方式,这样方便定义引用成员函数指针类型的数组,在菜单驱动程序中很有帮助,具体代码如下:

typedef void(A::*PMA)(char *, const char *);
PMA pmf= &A::strcat; // pmf是PMF类型(类A成员指针)的变量

注:结构体和联合体的成员指针,依旧是地址,而不是偏移量!

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/captain_wangnb/article/details/50505353
上一篇柔性数组
下一篇内存对齐原则
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭