1.类成员指针
- 对象的成员要占用存储空间, 因此也有地址, 可以定义指向对象成员的指针变量,
一般形式为:
数据成员类型 *指针变量名=初值;
eg:
int *ptr=&now.hour; //指向对象数据成员的指针变量
now成员的hour成员的地址,&(now.hour)
- C++比C语言有更严格的静态类型, 更加强调类型安全和编译时检查。
- 因此, C++的指针被分成数据指针、 函数指针、 数据成员指针、 成员函数指针四种, 而且不能随便相互转换。
其中前两种是C语言的,称为普通指针(ordinary pointer) ;
后两种是C++专门为类扩展的,称为成员指针(pointer to member) 。 - 成员指针与类的类型和成员的类型相关, 它只应用于类的非静态成员。 由于静态类成员不是任何对象的组成部分, 所以静态成员指针可用普通指针。
2.数据成员指针
数据成员类型 类名::*指针变量名=成员地址初值;
eg:
class Data//Data类
{
typedef unsigned int index;//类型成员
public:
char get() const;//成员函数,get()函数不能改变数据成员的值
char get(index st, index eb) const;//成员函数
string content;//数据成员
index cursor ,top, bottomo;//数据成员
};
- 指向content的指针的完全类型是“指向string类型的Data类成员的指针” ,
即:
String Data::*ps=&Data::content; //指向Data::content的成员指针
&(Data::content)
3.成员函数指针
- 定义成员函数的指针时,必须确保在三个方面与它所指函数的类型相匹配:
①函数形参的类型和数目, 包括成员是否为const(成员函数也可以为const)。
②返回类型。
③所属类的类型。 - 定义的一般形式为:
返回类型 (类名::*指针变量名)(形式参数列表)=成员地址初值;
或
返回类型 (类名::*指针变量名)(形式参数列表) const =成员地址初值;
若成员函数是const的,则要在这里加const
eg:
例如“char get() const”成员函数的指针可以这样定义和初始化:
char (Data::*pmf)() const = &Data::get; //指向Data::get()的成员指针
typedef char (Data::*GETFUNC)(Data::index,Data::index)const; //类型别名GETFUNC
这样指向get成员函数的指针的定义可以简化为:
GETFUNC pfget = &Data::get; //定义成员函数指针pfget
GETFUNC是类型
4.使用类成员指针
- 通过对象成员指针引用(.*) 可以从类对象或引用及成员指针间接访问类成员,
或者通过指针成员指针引用(->*) 可以从指向类对象的指针及成员指针访问类成员。 - 对象成员指针引用运算符左边的运算对象必须是类类型的对象,
指针成员指针引用运算符左边的运算对象必须是类类型的指针,
两个运算符的右边运算对象必须是成员指针。 - 成员指针间接引用运算符的表格如下
运算符 功能 目 结合性 用法
.* 对象成员指针引用 双目 自左向右 object.*member_pointer
->* 指针成员指针引用 双目 自左向右 pointer->*member_pointer
Data d, *p=&d; //指向对象d的指针
int Data::*pt = &Data::top; //pt为指向数据成员top的指针,pt是int型的指针,他需要指向Data类的数据成员,
将top的地址赋值给pt,但是top属于Data类
int k = d.top; //对象成员引用, 直接访问对象, 直接访问成员, 与下面等价
k = d.*pt; //对象成员指针引用, 直接访问对象, 间接访问成员
k = p->top; //指针成员引用, 间接访问对象, 直接访问成员, 与下面等价
k = p->*pt; //指针成员指针引用, 间接访问对象, 间接访问成员
char (Data::*pmf)(int,int) const; //pmf为成员函数指针,返回值类型:char,形参类型都是:const的,int的
pmf = &Data::get; //指向有两个参数的get函数,将get函数的地址赋值给pmf,要加上类和域运算符::
char c1 = d.get(0,0); //对象直接调用成员函数, 与下面等价
char c2 = (d.*pmf)(0,0); //对象通过成员函数指针间接调用成员函数
char c3 = (p->*pmf)(0,0); //指针间接引用对象通过成员函数指针间接调用成员函数
5.this指针
- 除了静态成员函数外, 每个成员函数都有一个额外的、 隐含的形参this(谁调用我,this就指向谁)。
在调用成员函数时, 编译器向形参this传递调用成员函数的对象的地址。
例如成员函数:
void Point::set(int a,int b) { x=a, y=b; } //成员函数定义
编译器实际上会重写这个函数为:
void Point::set(Point* const this,int a,int b)//调用对象的地址会传递给this
{ this->x=a,this->y=b; }
调用set成员函数的对象,它的x被赋值为了a
eg:
对应的函数调用:
one.set(10,10); //调用成员函数,one是由point类生成的对象
编译器实际上会重写这个函数调用为:
Point::set(&one,10,10); //调用成员函数
//set是Point类的成员函数,&one是调用对象的地址
using namespace std;
class Point
{
public:
Point(int a,int b)
{
x=a;
y=b;
}
void MovePoint(int a, int b)
{
x=x+a;
y=y+b;
}
void print()
{
cout<<"x="<<x<<",y="<<y<<endl;
}
private:
int x,y;
};
int main()
{
Point pt1(10,10);
pt1.MovePoint(2,2);
pt1.print;
return 0;
}
(1)当对象pt1调用MovePoint(2,2)函数时, 即将pt1对象的地址传递给了this指针。
MovePoint函数的原型应该是:
void MovePoint( Point *this, int a, int b);
(2)MovePoint函数中便成为:
void MovePoint(int a, int b)
{
this->x+=a;
this->y+=b;
}
(3)MovePoint函数体等价为:this等价于pt1
pt1.x+=a;
pt1.y+=b;
6.什么时候会用到this指针
- (1) 在类的非静态成员函数中返回类对象本身的时候, 直接使用return *this;
- (2) 当参数与数据成员名相同时, 如this->n = n (不能写成n=n) 。
- eg:
class point
{
public:
point(float x, float y)//构造函数
{
this->x=x;//this->x表示private中声明的x;x表示构造函数point(float x,float y)中的 x。
this->y=y;//this->y表示private中声明的 y;y表示构造函数point(float x,float y)中的 y
}
private:
float x,y;
};
(1)假设Point类有getX这样一个非static函数:
double Point::getX();
编译以后形式如下:
double getX(Point *const this);//可以看出, this指针的指向不允许改变, 所以this指针原本就是const指针。
(2)
如果成员函数是常函数,也就是下面的定义:
double Point::getX()const;
编译后会变成:
double getX(const Point *const this);//后面的const是系统本来就加上的
可以看出, 既不允许改变this指针的指向, 也不允许改变this指向的内容。