指向类的成员的指针
类的成员本身也是一个变量,函数或者对象等。因此也可以直接将它们的地址存放到一个指针变量中,这样就可以使指针直接指向对象的成员,进而可以通过这些指针访问对象的成员。需要指出的是,通过指向成员的指针只能访问公有的数据成员和成员函数。指向对象的成员的指针使用前要先声明,再赋值,然后才能访问。
1,指向数据成员的指针
格式如下:
类型说明符 类名::* 数据成员指针名;
声明了一个指向数据成员的指针后需要对其进行赋值,也就是要确定指向类的哪一个成员。对数据成员指针赋值的一般格式如下:
数据成员指针名 = &类名::数据成员名;
对于普通变量,用&运算符就可以得到它的地址,将这样的地址赋值给相应的指针就可以通过指针访问变量。但是类的声明值确定了各个数据成员的类型,所占内存大小以及它们的相对位置,在声明时并不是为数据成员分配具体的地址。因此,经过上述赋值之后只是说明了被赋值的数据成员指针是专门用于指向哪个数据成员的,同时在指针中存放数据成员在类中的相对位置(即相对于起始地址的地址偏移量)。由于类是通过对象而实例化的,只有在定义了对象时才能为具体的对象分配内存空间,这时只要将对象在内存中的起始地址与成员指针中存放的相对偏移结合起来就可以访问到对象的数据成员了。用数据成员指针访问数据成员可通过以下两种格式来实现:
对象名.*数据成员指针名 或 对象指针名->*数据成员指针名
例4.9:
#include <iostream.h>
class A
{
public:
A(int i)
{
z = i;
}
int z;
};
void main()
{
A ob(5);
A *pc1;
pc1 = &ob;
int A::*pc2;
pc2 = &A::z;
cout<<ob.*pc2<<endl;
cout<<pc1->*pc2<<endl;
cout<<ob.z<<endl;
}
2,指向成员函数的指针
格式如下:
类型说明符 (类名::*指针名) (参数表)
赋值的一般格式:
成员函数指针名 = &类名::成员函数名;
对于一个普通函数而言,函数名就是它的起始地址,将起始地址赋给指针,就可以通过指针调用函数。虽然类的成员并不在每个对象中复制一份拷贝,但是语法规定必须要通过对象来调用成员函数,因此上述赋值之后,还不能用指针直接调用成员函数,而是需要首先声明类的对象,然后通过以下两种形式利用成员函数指针调用成员函数:
(对象名.*成员函数指针名)(参数表) 或 (对象指针名->*成员函数指针名)(参数表)
例4.10:
#include <iostream.h>
class Coord
{
public:
Coord(int a = 0, int b = 0)
{
x = a;
y = b;
}
int getx()
{
return x;
}
int gety()
{
return y;
}
private:
int x, y;
};
void main()
{
Coord op(5,6); //定义对象op
Coord *pc1 = &op; //声明对象指针pc1并赋值
int(Coord::*pc_getx)(); //声明成员函数指针pc_getx
pc_getx = Coord::getx; //给成员函数指针赋值
cout<<pc1->getx()<<endl; //使用对象指针pc1访问成员函数getx()
cout<<op.getx()<<endl; //使用对象名访问成员函数getx()
cout<<(op.*pc_getx)()<<endl; //使用成员函数指针访问成员函数getx()
cout<<(pc1->*pc_getx)()<<endl; //使用成员函数指针访问成员函数getx()
}