一个类有两种基本的成员:函数成员和数据成员。同样的,指向成员的指针也有两种:指向函数成员的指针和指向数据成员的指针。后则其实并不常用,因为类一般是不含有公共数据成员的,仅当用在继承用C写的代码时协调结构(struct)和类(class)时才会用到。 指向成员的指针是C++语法中最难以理解的构造之一,但是这也是一个C++最强大的特性。它可以让你调用一个类的函数成员而不必知道这个函数的名字。这一个非常敏捷的调用工具。同样的,你也可以通过使用指向数据成员的指针来检查并改变这个数据而不必知道它的成员名字。
指向数据成员的指针
尽管刚开始时,指向成员的指针的语法会使你有一点点的迷惑,但你不久会发现它其实同普通的指针差不多,只不过是*号的前面多了::符号和类的名字,例:定义一个指向int型的指针:
int * pi;
定义一个指向为int型的类的数据成员:
int A::*pmi; //pmi是指向类A的一个int型的成员
你可以这样初始化它:
class A
{
public:
int num;
int x;
};
/*
指向类数据成员的指针与普通指针的初始化及赋值方式不太一样,因为普通指针在给其初始化或赋值时,赋予的是一个实际的对象,如 int j; int *i=&j;
而指向数据成员的指针赋予的是一个目前还不存在的一个类成员的地址,而这个地址只有在使用实际类对象进行调用时才会真正的确定下来,如下:
*/
int A::*pmi = & A::num;
上面的代码是声明一个指向类A的一个int型的num成员并将它初始化为这个num成员的地址.通过在pmi前面加上*你就可以使用和更改类A的num成员的值:
A a1, a2;
int n=a1.*pmi; //把a1.num赋值给n
a1.*pmi=5; // 把5赋值给a1.num
a2.*pmi=6; // 把6赋值给6a2.num
如果你定义了一个指向类A的指针,那么上面的操作你必须用 ->*操作符代替:
A * pa=new A;
int n=pa->*pmi;
pa->*pmi=5;
指向函数成员的指针
它由函数成员所返回的数据类型构成,类名后跟上::符号、指针名和函数的参数列表。举个例子:一个指向类A的函数成员(该函数返回int类型)的指针:
class A
{
public:
int func ();
};
int (A::*pmf) ();
上面的定义也就是说pmf是一个指向类A的函数成员func()的指针.实际上,这个指针和一个普通的指向函数的指针没什么不同,只是它包含了类的名字和::符号。你可以在在任何使用*pmf的地方调用这个函数
func():
pmf=&A::func;
A a;
(a.*pmf)(); //调用a.func()
如果你先定义了一个指向对象的指针,那么上面的操作要用->*代替:
A *pa=&a;
(pa->*pmf)(); //调用pa->func()
指向函数成员的指针要考虑多态性。所以,当你通过指针调用一个虚函数成员时,这个调用将会被动态回收。另一个需要注意的地方,你不能取一个类的构造函数和析构函数的地址。