对象指针
一、对象指针的一般概念
- 和基本类型的变量一样,每个对象在初始化之后都会在内存中占有一定的空间
- 对于一个对象来说,既可以通过对象名进行访问,也可以通过对象的地址来访问一个对象
- 一个对象包含数据成员和成员函数,但对象所占据的内存空间只是用于存放数据成员的,
函数成员不在每一个对象中存储副本。
对象遵循一般变量指针的各种规则,声明对象指针的一般语法形式为:
类目名 *对象指针名;
//假如现在已经有个Point的类
Point *ptr; //声明point类的对象指针变量ptr
Point point; //声明point类的对象point
ptr=&point; //将对象point的地址赋给对象指针ptr
对于对象指针来说,除了一般的使用之外,还有一种方便地访问对象地成员的方法:
对象指针名 *->*成员名
这种形式与:"(*对象名).成员名 " 的访问形式是等价的
class Point//定义一个Point的类
{
public:
Point(int x=0,int y=0):x(x),y(y){}
int getX() const {return x;}
int getY() const {return y;}
private:
int x,y;
};
int main()
{
Point A(3,4); //声明一个对象A
Point *p=&A;
//p为Point的一个对象指针,指向对象A;
//通过对象名访问
cout<< A.getX()<<endl;
//通过指针访问(一般的方法)
cout<<(*p).getX()<<endl;
//通过指针访问(特殊的方法)
cout<< p->getX()<<endl;
}
拓展:
在之前的C++课程教材上曾用过这一个程序案例:
class Fred; //前向引用声明
class Barney
{
Fred x; //错误:类Fred的定义尚不完善
};
class Fred
{
Barney y; //正确:类Barney在此类之前已经定义
}
这个错误在之前似乎是没有办法解决的,但是运用指针,成为一下形式,语法上就可以通过。
class Fred;//前向引用声明
class Barney
{
Fred *x; //正确:类Barney中声明一个类Fred的
//指针(不是对象),这是允许的。
};
class Fred
{
Barney y;//正确:类Barney在此类之前已经定义
}
二、this指针
this 指针是一个隐含于每一个类的非静态成员函数中的特殊指针(包含构造函数和析构函数),他用于指向正在被成员函数操作的对象。
细节:
- this指针实际上是类成员函数的一个隐含参数。在成员函数开始执行前构造的,在成员的执行结束后清除。
- 在调用类的成员函数时,目的对象的地址会自动作为该参数的值,传递给被调用的成员函数,这样被调函数就能够通过this指针来访问目的对象的数据成员。
- 对于类成员函数的调用时,每次对成员函数的调用都存在一个目的对象,this指针就是指向这个目的对象的指针。
- 当通过一个对象调用成员函数进行操作时,系统先将该对象的地址通过该参数传递给成员函数,成员函数对对象的数据成员进行操作时,就隐含使用了this指针。
可能看的有点懵,那就直接上代码!
class Point//定义一个Point的类
{
public:
Point(int x=0,int y=0):x(x),y(y){}
int getX() const {return x;}
//this指针在调用时会被当做参数传进来指明这个对象。
//在调用的时候 实际上的形式
//int getX() const{return this->x;}
//只是把“this->”隐藏了
int getY() const {return y;}
private:
int x,y;
};
int main()
{
Point A(3,4); //声明一个对象A
A.getx();
//A对象的this指针就会以隐含参数的形式给getX()函数,
//进而把使得该函数可以对A的数据成员进行操作。
}
注意:
- this是一个指针常量,对于常成员函数来说,this同时又是一个指向常量的指针。
这里的const与指针可以参考之前指针(一)里面的2.2。
- this指针不能在静态函数中使用
因为静态函数表示了整个类范围的意义,而this指针却实实在在的对于一个对象。
拓展:
当局部作用域中声明了与类成员同名的标识符时,对该标识符的直接引用代表的时局部作用域中声明的标识符,这是为了访问该类的成员,可以通过this指针。
class Point//定义一个Point的类
{
public:
Point(){};
int getX()
{
int x;//声明一个局变量的x;
x=1;
this->x=2;//对类成员同名的x的访问
return x;
//注意此时return返回的时局部变量的x
//调用getX()将返回的值是:1
//如果想返回类成员同名的x
//就要用this指针,将return语句改为:
//return this->x;
//再调用getX()将返回的值是:2
}
private:
int x=0,y=0;
};
三、指向类的非静态成员函数的指针
类的成员自身也是一些变量、函数或者对象等,因此也可以直接将它们的地址存放到一个指针变量中,这样就可以通过指针直接指向对象的成员,进而通过这些指针访问对象的成员。
声明指针的一般语法形式:
1. 声明指向数据成员的指针
类型说明符 类名:: * 指针名;
2. 声明指向成员函数的指针
类型说明符 (类名:: * 指针名)(参数表);
对数据成员指针赋值的一般语法形式:
指针名 =&类名::数据成员名;
利用指针调用类的成员函数:
(对象名.* 类成员指针名)(参数表)
class Point//定义一个Point的类
{
public:
Point(){};
int getX() {return x;}
int getY() {return y;}
int num=3;
private:
int x=0,y=0;
};
int main()
{
Point A;
//声明指向Point类数据成员的指针
int Point::*p;
//将Point类的数据成员地址赋给指针。
p=&Point::num;
//使用
cout<<A.*p<<endl;//或者
//注意要保证num的可以访问到
//x的数据成员是私有的,则无法访问
//声明指向函数成员的指针
int (Point::*ptr)();//注意形式要和所指向的函数声明形式一样
//将Point类的数据成员地址赋值给指针
ptr=&Point::getX;//函数名即为函数的地址
cout<<(A.*ptr)();//使用时,注意和声明时的形式保持一致
}
四、指向类的静态成员的指针
对类的静态成员的访问是不依赖于对象的,因此可以用普通的指针来指向和访问静态成员。
class A//定义一个简单的A类
{
public:
static void print()
{cout << x << endl;}
int gety() { return y; }
static int x;
int y;
};
int A::x=1;
int main()
{
int* p1 = &A::x;
int A::* p2 = &A::y;//对比 非静态;
void (* ptr1)() = &A::print;
int (A:: * ptr2)() = &A::gety;//对比 非静态的;
}