C++面向对象程序设计 - 对象指针和this指针

        在C++学习中,指针是一个用于指向另一个变量的地址的变量。理解指针有一定难度,但是理解它的工作原理后,会发现它们是非常强大和有用的工具。指针可以用来指向一般的变量,也可以指向对象。

一、指向对象的指针

        在建立对象时,编译系统会为每一个对象分配一定的存储空间,以存放其成员。对象空间的起始地址就是对象的指针。

        定义指向类对象的指针变量的一般形式为:

类名 *对象指针名

        首先创建一个类,代码如下:

class Timer{public:int hour;int minute;int second;Timer(){hour = 0;minute = 0;second = 0;}Timer(int h, int m, int s): hour(h), minute(m), second(s){}void show_time(){cout <<hour <<':' <<minute <<':' <<second <<endl;}
};

        定义指向Timer类对象的指针变量,代码如下:

int main(){Timer *pt, t1;pt = &t1;return 0;
}

        通过对象指针访问对象成员,代码如下:

int main(){Timer *pt, t1;pt = &t1;// 直接访问hourcout <<"hour:" <<pt->hour <<endl;cout <<"hour:" <<(*pt).hour <<endl;// 访问成员函数pt->show_time();(*pt).show_time();return 0;
}

       运行结果如下:

  1. pt->hour这种方式是通过 "->"运算符直接调用指针pt所指向对象的hour成员变量。
  2. (*pt).hour这种方式是通过解引用 *pt 来获取指针pt所指向的对象,然后通过点"."运算符来调用该对象的hour成员变量。

        这两种访问指针所指向对象的成员函数的等价方式,pt是指向Timer对象的指针。大多情况下,使用pt->hour和pt->show_time()的方式更为简洁和直观。

二、指向对象成员的指针

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

        定义指向对象数据成员的指针变量的一般形式:

数据类型名 *指针变量名

        在类外通过指向对象数据成员的指针变量访问对象数据成员hour,代码如下:

int main(){Timer t1;int *ph;// 指向Timer对象数据成员hourph = &t1.hour;// 输出ph指针指向的地址cout <<"hour:" <<ph <<endl;// 输出ph指针指向数据成员变量值cout <<"hour:" <<*ph <<endl;return 0;
}

        从运行结果上可以看出,现在所输出的ph是指向Timer成员变量hour的地址,通过*ph则可以得到该成员变量的值,如下图:

        定义指向普通函数的指针变量方法的形式:

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

        这里定义一个普通函数,并通过指针指向它,代码如下:

#include <iostream>
using namespace std;void sortArray(int arr[], int size){cout <<"Array:" <<&arr <<", size:" <<size <<endl;
}int main(){// 声明p指向void型函数的指针变量void (*p)(int arr[], int size);// 将 sortArray函数的入口地址赋给指针变量pp = sortArray;// 定义参数列表数组int nums[3] = {2, 3, 5};// 调用sortArray函数(*p)(nums, 3);return 0;
}

        输出结果如下图:

        而定义一个指向对象成员函数的指针变量则比较复杂一些,和定义指向普通函数的指针变量有所不同。编译系统要求在上面的赋值语句中,指针变量的类型必须与赋值好右侧函数的类型相匹配,主要以下三个方法:

  1. 函数参数的类型和参数个数;
  2. 函数返回值的类型;
  3. 所属的类;

        定义指向公用成员函数的指针变量的一般形式:

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

        使指针变量指向一个公用成员函数的一般形式:

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

        代码示例如下:

// 定义指向Timer类公用成员函数的指针变量
void (Timer::*ps)();
// 指针变量指向Timer类公用成员函数show_time
ps = &Timer::show_time;
// 调用对象t1中ps指向的成员函数
(t1.*ps)();

        运行结果如下:

        其实,以上定义成员函数指针变量同时,可以直接赋值Timer类成员函数址地,其得到结果是一样的。代码如下 :

// 定义指向Timer类公用成员函数的指针变量,并且指针变量指向Timer类公用成员函数show_time
void (Timer::*ps)() = &Timer::show_time;
// 调用对象t1中ps指向的成员函数
(t1.*ps)();

        成员函数不是存放在对象的空间中,而是存放在对象外的空间中,如果多个同类的对象,它们是可以共用同一个函数代码段。因此,赋给变量ps的是这个公用的函数代码段的入口地址。

三、对象数组的指针

        在C++中,处理数组和指向数组的指针时,可以通过“引用”或“指针”到数组的方式。在上一篇中获取对象数组长度时,也讲到对象数组相关内容。

址地:C++面向对象程序设计 - 数组与sizeof、对象指针使用-CSDN博客

       先通过一段代码了解下:

int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *ref = arr;
// 或 
int (*ref)[10] = &arr;        //通过指针方式
// 或
int (&ref)[10] = arr;         //通过引用方式

        1、 ref是一个指向整数的指针,当把数组arr赋值给ref时,arr会自动转换为指向数组第一个元素的指针(即&arr[0])。现在ref指向数组的第一个元素,即整数值1.可以通过解引用ref或者进行指针算术来访问数组其他元素。示例代码如下:

#include <iostream>
using namespace std;int main(){int arr[10] = {1, 5, 3, 4, 5, 6, 7, 8, 9, 10};int *ref = arr;cout <<"first value:" <<*ref <<endl;ref++;cout <<"seocnd value:" <<*ref <<endl;return 0;
}

       运行结果可以看出当指针移到下个位置时,则对接数组arr第二个元素(即&arr[1]),如下图:

        2、 *ref 是一个指向含有10个整数的数组的指针;&arr取得了整个数组arr地址并将它赋值给ref来初始化它;可以通过解引用ref得到整个数组,而不仅仅是数组第一个元素。示例代码如下 :

#include <iostream>
using namespace std;int main(){int arr[10] = {1, 5, 3, 4, 5, 6, 7, 8, 9, 10};int (*ref)[10] = &arr; cout <<"first value:" <<(*ref)[0] <<endl;cout <<"seocnd value:" <<(*ref)[1] <<endl;return 0;
}

        以上代码可以看出,这里ref不再指向某个子元素,而是整个数组arr,所以需要通过索引进行取值。结果如下图:

        3、 &ref实际上是一个数组的引用,而不是指针。arr是数组的名称,它是数组本身的引用,所以ref是数组arr的一个别名,他们指向相同的内存位置,这里的ref也能直接访问数组的元素。示例代码如下:

#include <iostream>
using namespace std;int main(){int arr[10] = {1, 5, 3, 4, 5, 6, 7, 8, 9, 10};int (&ref)[10] = arr;cout <<"first value:" <<ref[0] <<endl;cout <<"seocnd value:" <<ref[1] <<endl;return 0;
}

        这里ref只是数组arr的一个别名,所以从代码中可以看出,直接使用ref取值即可。结果如下图:

        在大多数情况下,数组的引用和指向数组的指针,在用法上很相似,但它们在类型上是有区别的。指针是一个变量,可以指向不同的地址。而引用则是一别名,必须在声明时初始化,不能重新绑定到另一个对象。

四、this指针

        每个成员函数中都包含一个特殊的指针,这个指针名是固定的,称为this。它是指向本类对象的指针,它可以调用本类中成员。this指针是隐式使用的,它是作为参数被传递给成员函数的。

        之前创建对象,定义构造函数时,形参都是以缩写方式声明的,如与成员变量一致,编译系统会直接报错。有人可能在想,就是想使用全称来声明形参,则可以通过显示使用this指针,解决这一问题。代码如下:

class Timer{public:int hour;int minute;int second;// this指针使用 -> 运算符调用成员Timer(){this->hour = 0;this->minute = 0;this->second = 0;}// *this指针通过点调用成员Timer(int hour, int minute, int second){(*this).hour = hour;(*this).minute = minute;(*this).second = second;}void show_time(){cout <<hour <<':' <<minute <<':' <<second <<endl;}
};

        此时编译程序,则不会报错了。以上代码中无参构造函数中直接使用 -> 运算符调用成员变量,和有参构造函数中*this通过点调用成员变量方式,在“一、指向对象的指针”中已说明,这里不再阐述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/596298.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ARM v8 Cortex R52内核 02 程序模型 Programmers Model

ARM v8 Cortex R52内核 02 程序模型 Programmers Model 2.1 关于程序模型 Cortex-R52处理器实现了Armv8-R架构。这包括&#xff1a; 所有的异常级别&#xff0c;EL0-EL2。 每个异常级别下的AArch32执行状态。 T32和A32指令集&#xff0c;其中包括&#xff1a; 浮点运算。 …

文件的随机读写--fseek,ftell,拷贝文件

想要查看fseek&#xff0c;ftell&#xff0c;函数&#xff0c;请登录这个网站&#xff1a; cplusplus.com - The C Resources Networkhttps://legacy.cplusplus.com/ 还有一个函数没有写出来&#xff0c;是rewind&#xff0c;它是&#xff1a;让⽂件指针的位置回到⽂件的起始位…

java.lang.NoClassDefFoundError: javax/validation/constraints/Min

1、报错截图 2、解决办法 添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId> </dependency>

论文润色康康我

想象一下&#xff0c;当您埋头苦干&#xff0c;终于完成了一篇研究论文或商业报告&#xff0c;那份成就感无疑是巨大的。然而&#xff0c;文章的完成只是第一步&#xff0c;如何让文章在众多作品中脱颖而出&#xff0c;才是摆在每一位作者面前的挑战。这时&#xff0c;意得辑的…

常见的加密方式总结(哈希算法、对称、非对称)

哈希算法是一种用数学方法对数据生成一个固定长度的唯一标识的技术&#xff0c;可以用来验证数据的完整性和一致性&#xff0c;常见的哈希算法有 MD、SHA、MAC 等。 对称加密算法是一种加密和解密使用同一个密钥的算法&#xff0c;可以用来保护数据的安全性和保密性&#xff0…

智慧牧场数据 7

1 体征数据采集 需求:获取奶牛记步信息 三轴加速度测量&#xff1a;加速度测量计反应的加速向量与当前的受力方向是相反&#xff0c;单位为g 陀螺仪&#xff0c;是用来测量角速度的&#xff0c;单位为度每秒&#xff08;deg/s&#xff09; 2000deg/s 相当于1秒钟多少转 1.1…

9(10)-1(2)-CSS 布局模型+CSS 浮动

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 一、CSS 布局模型1 流动模型&#xff08;标准流&#xff09; 二、CSS 浮动1 浮…

C++从入门到精通——类的定义及类的访问限定符和封装

类的定义及类的访问限定符和封装 前言一、类的定义类的两种定义方式成员变量命名规则的建议示例 二、类的访问限定符和封装访问限定符访问限定符说明C为什么要出现访问限定符例题 封装例题 前言 类的定义是面向对象编程中的基本概念&#xff0c;它描述了一类具有相同属性和方法…

VTK中polydata的属性数据结构表示和用法

vtk中通过vtkDataArray进行数据的存储&#xff0c;通过vtkDataObject进行可视化数据的表达&#xff0c;在vtkDataObject内部有一个vtkFieldData的实例&#xff0c;负责对数据的表达&#xff1a; vtkFieldData存储数据的属性数据&#xff0c;该数据是对拓扑结构和几何结构信息的…

【C++】红黑树讲解及实现

前言&#xff1a; AVL树与红黑树相似&#xff0c;都是一种平衡二叉搜索树&#xff0c;但是AVL树的平衡要求太严格&#xff0c;如果要对AVL树做一些结构修改的操作性能会非常低下&#xff0c;比如&#xff1a;插入时要维护其绝对平衡&#xff0c;旋转的次数比较多&#xff0c;更…

【Linux】环境基础开发工具使用——vim使用

Linux 软件包管理器 yum 什么是软件包 1.在 Linux 下安装软件 , 一个通常的办法是下载到程序的源代码 , 并进行编译 , 得到可执行程序 . 2.但是这样太麻烦了 , 于是有些人把一些常用的软件提前编译好 , 做成软件包 ( 可以理解成 windows 上的安装程序) 放在一个服务器…

AI无人商店背后,是上千个印度人通过摄像头看美国人买西蓝花?

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 AI无人商店&#xff0c;背后疑似是1000印度人看摄像头&#xff1a;大厂的「拿货即走」没有走…