指向对象的指针

在建立对象的时候,变异系统会给每一个对象分配一定的存储空间,以存放其成员。
对象空间的起始地址就是对象的指针。可以定义一个指针变量,用来存放对象的指针。
一个简单的示例1.1:
#include<iostream>
using namespace std;
class Student
{
public:
int num;
int score;
Student(int ,int );//声明构造函数
void Print();//声明输出信息函数
};
Student::Student(int n,int s)
{
num=n;
score=s;
}
void Student::Print(){
cout<<num<<"\t"<<score<<endl;
}
int main(){
Student stud(1,100);//实例化一个对象
Student *p=&stud;//定义一个指向对象的指针,并使用对象stud的地址初始化
cout<<"*p.num:"<<(*p).num<<endl;//使用指向对象的指针调用数据成员的方式一
cout<<"p->score:"<<p->score<<endl;//使用指向对象的指针调用数据成员的方式二
(*p).Print();
p->Print();
return 0;
}



指向对象成员的指针

对象有地址,存放对象初始地址的指针变量就是
指向对象的指针变量
对象中的成员也有地址,存放对象成员地址的指针变量就是
指向对象成员的指针变量

1.指向对象数据成员的指针

定义指向对象数据成员的方法和定义指向普通变量的方法相同:
数据类型    *    指针变量名
p=&t1.hour;//将对象t1的数据成员hour的地址赋给p,p指向t1.hour
cout<<*p<<endl;//输出t1.hour的值

2.指向对象成员函数的指针

定义指向成员函数的指针和定义指向普通函数的指针的方法是不同的。
定义指向普通函数的指针的方法是这样的:
数据类型名(* 指针变量名)(参数列表);
如:
void  (*p)(int n,int m);//p是指向void型函数的指针变量
p=fun;//将fun函数的入口地址赋给指针变量p,p就指向了函数fun
(*p)(a,b);//调用fun函数,其中,a,b是实参

而定义一个指向对象成员函数的指针变量则比较复杂一些。

如果我们直接按照上面的方法定义指针变量,将对象成员函数名赋给指针变量p:
void (*p)();
p=t1.Print();

编译会出现错误
成员函数与普通函数的一个最根本区别:它是类中的一个成员。

编译系统要求上面的复制语句中,指针变量的类型必须与赋值号右侧函数的类型相匹配,要求在一下3个方面要匹配:
1.函数参数的类型和参数个数
2.函数返回值的类型
3.所属的类
前两个是匹配的,而第三点不匹配。
指针变量p与类无关,而Print()却属于Student类。


定义指向成员函数的指针变量应该采用以下形式:
void (Student::*p)();//定义p为指向Student类中公共成员函数的指针变量

数据类型名(类名::*指针变量名)(参数表列);

我们知道,所有的Student类实例化得到的对象都是公用一个成员函数的,所以我们没有必要指定它是指向那个对象的成员函数的指针,我们只需要定义它是指向该类的成员函数就可以了。

使
指针变量指向一个公用成员函数的一般形式为:
p=&Student::Print;

指针变量名=&类名::成员函数名;

在使用时,仍然需要将指针放到具体的对象中使用,(*p)的作用等价于Print()
stud.(*p);//作用与stud.Print()的作用等价

=================一个使用对象指针的例子1.2===========
#include<iostream>
using namespace std;
class Student
{
public:
int num;
int score;
Student(int ,int );
void Print();
};
Student::Student(int n,int s)
{
num=n;
score=s;
}
void Student::Print(){
cout<<num<<"\t"<<score<<endl;
}
int main(){
Student stud(1,100);
cout<<"stud.Print()"<<endl;
stud.Print();//直接调用对象stud的成员函数Print();
Student *p_class=&stud;//定义指向对象stud的指针;
cout<<"p_class->Print()"<<endl;
p_class->Print();//通过指向对象的指针调用成员函数Print();
void (Student::*p_fun)();//声明p_fun是指向Student中的函数的指针
p_fun=&Student::Print;//是p_fun指向Student类公用成员函数Print()
cout<<"(stud.*p_fun)()"<<endl;
(stud.*p_fun)();//调用对象stud中的p_fun所指向的成员函数(即:stud.Print)
return 0;
}




this指针

每个对象中的数据成员都分别占用存储空间,如果对同一个类定义了n个对象,则有n组同样大小的空间一存放n个对象中的数据成员。
单数不同的对象都调用同一段函数代码段。
那么,当不同对象的成员函数引用数据成员时,怎么能保证引用的是所制定的对象的数据成员呢?
实际上,在每一个成员函数中,都包含一个特殊的指针,这个指针的名字是固定的,称为this指针。
它是指向本类对象的指针,它的值是当前被调用的成员函数所在的对象的起始地址。

例如:
Print()函数中

	cout<<num<<"\t"<<score<<endl;

实际上是

	cout<<this->num<<"\t"<<this->score<<endl;

this指针式隐式使用的,它是作为参数被传递给成员函数。

在程序中的函数:
void Student::Print(){
cout<<num<<"\t"<<score<<endl;
}

C++编译系统会自动处理成:

void Student::Print(Student *this){
cout<<this->num<<"\t"<<this->score<<endl;
}

即在成员函数的形参表列中增加一个this指针。在调用成员函数stud.Print()时,实际上是用以下方式调用的:

stud.Print(&stud);


C++中的对象指针的更多相关文章

  1. C++中的智能指针、轻量级指针、强弱指针学习笔记

    一.智能指针学习总结 1.一个非const引用无法指向一个临时变量,但是const引用是可以的! 2.C++中的delete和C中的free()类似,delete NULL不会报"doubl ...

  2. C++中的函数指针和函数对象总结

    篇一.函数指针函数指针:是指向函数的指针变量,在C编译时,每一个函数都有一个入口地址,那么这个指向这个函数的函数指针便指向这个地址.函数指针的用途是很大的,主要有两个作用:用作调用函数和做函数的参数. ...

  3. vue中computed计算属性与methods对象中的this指针

    this 指针问题 methods与computed中的this指针 应该指向的是它们自己,可是为什么this指针却可以访问data对象中的成员呢? 因为new Vue对象实例化后data中的成员和c ...

  4. C# CLR via 对象内存中堆的存储【类型对象指针、同步块索引】

    最近在看书,看到了对象在内存中的存储方式. 讲到了对象存储在内存堆中,分配的空间除了类型对象的成员所需的内存量,还有额外的成员(类型对象指针. 同步块索引 ),看到这个我就有点不懂了,不知道类型对象指 ...

  5. 【转】vector中对象指针的排序

    原文:http://blog.csdn.net/tanlijun37/article/details/1948493 vector中对象指针的排序,初步想法是1: 把对象指针存到vector,重载bo ...

  6. java 对象变量 c++对象指针 初始化对象变量的2中方法

    java 对象变量 c++对象指针 java null引用 c++ null指针 Date deadline  是 对象变量,它可以引用Date类型的对象,但它不是一个对象,实际上它也没有引用对象. ...

  7. 获得函数返回值类型、参数tuple、成员函数指针中的对象类型

    //function_traits.h,获得函数返回值类型.参数tuple.成员函数指针中的对象类型 //参考https://github.com/qicosmos/cosmos/blob/maste ...

  8. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  9. QT中使用函数指针

    想仿命令行,所以定义了一个类,让一个String 对应一个 function,将两者输入list容器. 类中定义了 QString commandStr; void (MainWindow::*com ...

随机推荐

  1. Linux内核空间-用户空间通信之debugfs

    一.debugfs文件系统简介 debugfs虚拟文件系统是一种内核空间与用户空间的接口,基于libfs库实现,专用于开发人员调试,便于向用户空间导出内核空间数据(当然,反方向也可以).debugfs ...

  2. Android 蓝牙( Bluetooth)耳机连接分析及实现

    Android 实现了对Headset 和Handsfree 两种profile 的支持.其实现核心是BluetoothHeadsetService,在PhoneApp 创建的时候会启动它. if ( ...

  3. signal()函数说明

    表头文件#include<signal.h> 功 能:设置某一信号的对应动作 函数原型:void (*signal(int signum,void(* handler)(int)))(in ...

  4. BZOJ 2330: [SCOI2011]糖果( 差分约束 )

    坑爹...要求最小值要转成最长路来做.... 小于关系要转化一下 , A < B -> A <= B - 1 ------------------------------------ ...

  5. Python的strip()与split()

    ==>the start 说实话刚开始我对strip()和split()这两个还真的不太懂,后来在网上查了资料才明白. 可能别人觉着这俩很好区分,但是我最开始确实是有点分不清的,或者说不太确定这 ...

  6. 几种能在O(n*log(n))时间排序

    线性时间排序   各种排序算法总结已经介绍了几种能在O(n*log(n))时间内培训n个数的算法.归并排序和堆排序达到了最坏情况下的上界:快速排序在平均情况下达到该上界.这些算法都有一个有趣的性质:在 ...

  7. Jquery 中each循环嵌套的使用示例教程

    1.从MVC返回的Json数据如下: 2.下面是客户端实现的示例: $.post("/admin/GetPermissionsForRole", function (data,st ...

  8. 解决基于BAE python+bottle开发上的一系列问题 - artwebs - 博客频道 - CSDN.NET

    解决基于BAE python+bottle开发上的一系列问题 - artwebs - 博客频道 - CSDN.NET 解决基于BAE python+bottle开发上的一系列问题 分类: python ...

  9. 幻世(OurDream)2D图形引擎使用教程9——处理操作输入(3)

    声明:本教程版权归Lizcst Software Lab所有,欢迎转载,但是转载必须保留本段声明文字,并注明文章来源:http://blog.csdn.net/kflizcst 谢谢合作! 现在我们该 ...

  10. JQuery5.04获取

    获取body:  $('body'); 或者 $(document.body); 获取元素标签:$('div');   $('a'); 获取ID: $('id'); 获取某个元素的某个属性: $('a ...