当前课程知识点:C++语言程序设计基础 > 第6章 数组、指针与字符串(二) > 对象指针 > 对象指针
对象指针
对象指针定义形式
类名 *对象指针名;
例:
Point a(5,10);
Piont *ptr;
ptr=&a;
通过指针访问对象成员
对象指针名->成员名
例:ptr->getx() 相当于 (*ptr).getx();
例6-12使用指针来访问Point类的成员
//6_12.cpp
#include <iostream>
using namespace std;
class 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(4, 5);
Point *p1 = &a; //定义对象指针,用a的地址初始化
cout << p1->getX() << endl;//用指针访问对象成员
cout << a.getX() << endl; //用对象名访问对象成员
return 0;
}
this指针
指向当前对象自己
隐含于类的每一个非静态成员函数中。
指出成员函数所操作的对象。
当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作时,就隐含使用了this指针。
例如:Point类的getX函数中的语句:
return x;
相当于:
return this->x;
曾经出现过的错误例子
class Fred; //前向引用声明
class Barney {
Fred x; //错误:类Fred的声明尚不完善
};
class Fred {
Barney y;
};
正确的程序
class Fred; //前向引用声明
class Barney {
Fred *x;
};
class Fred {
Barney y;
};
大家好
欢迎回来继续学习
C++语言程序设计
这一节呢
我们来学习对象指针
对象指针呢
也就是用来容纳
一个对象地址的指针
它指向的是对象
接下来我们就来看
对象指针的定义和使用
我们来看定义一个对象指针呢
实际上跟定义其他类型的指针
是一样的
都是指针名
前面有个*
再往前呢是类型名
那么类名也就是个类型名
对吧
所以我们看这段程序代码的例子
比如说我们定义一个
point类型的指针 ptr
也就是说
这个指针是准备着用来存放
point对象地址的
那么在此之前呢
我们已经定义
已经构造了一个point对象a
所以我们就可以将a的地址
赋给这个指针
所以这跟一般的
指向数据变量的指针是一样的
但是呢
我们用指针去访问
所指向的对象的时候
怎么访问呢
我们去访问对象
一般都是要通过对象
去访问对象的成员
公有的接口 对吧
所以我们怎么样通过对象指针
去访问对象成员呢
那么这里给出的呢
是一个非常简洁的形式
就是对象指针名
好象然后是一个箭头
后面是成员名
其实那不是一个箭头
是一个减号后接一个大于号
都是西文符号
但是它的样子就像箭头
它的含义也是一个指向的含义
那么它实际上
语法上等同于什么呢
比如说ptr箭头getx
那就等同于
我用ptr这个指针进行指针运算
那么就找到了它指向的对象
就是对象a
那么通过a去访问
通过对象去访问
它的公有成员函数的时候
我们当然是通过
对象名.成员名的方式访问了
所以呢
实际上就是*ptr().getx
这是我们原本的通过指针
访问对象的公有成员的方式
但是这种写法呢
毕竟过于繁琐
所以在C++中呢
一般推荐另外一种写法
就是用一个
像箭头一样的东西指过去
ptr减号大于号
合起来算个箭头吧
然后getx 这样来访问
接下来在下面这个例题中呢
我们就要用指向对象的指针
来访问point类的对象
在这个程序中呢
我们在主函数中
定义了点类的对象a
然后又定义了
指向点类对象的指针p1
用已经定义好的对象a的地址
去初始化p1
这样的话
p1是指向对象a了
那么用p1去访问对象a
怎么访问呢
我们知道
实际上我们可以用*p1
指针运算符去访问
但是访问到对象a以后
我们还要再去找
它的函数
那么还要点 函数
*().点合起来
可以转化成另外一种形式来写
就是箭头是一个减号大于号
用p1去访问了对象a的getx函数
那再看看接下来用a
去访问getx函数
如果我们自己去运行一下
看一下输出结果
你会发现它的效果是一样的
大家可以课后
自己去运行一下这个程序
接下来
我们要学习一个很好玩的指针
this指针
它是什么呢
是指向当前对象自己的指针
为什么有的指针
还要指向当前对象自己
这个当前对象说的是什么
是谁
我们想想
当我们用对象名.函数名的方式
去调用对象的接口函数的时候
公有函数的时候
比如说
我们用对象名.getx
这个getx函数
就会把这个对象的x数据成员值
返回回来
其实大家有没有想过
这样一个问题
当你在调用getx这个函数的时候
其实可能
不止一个对象被构造过
在当前系统中
存在着好几个对象了
这个getx怎么就能知道
去把谁的x坐标反馈回来呢
那么知道了this指针是怎么回事
这个问也就解决了
实际上呢
这个this指针
它是隐含于类的每一个
非静态的成员函数中的
也就是
属于对象的成员函数
像比如point类的getx函数
gety函数
它肯定是属于对象的
必须通过
对象名.函数名的方式访问
它会准确地把这个对象的x坐标
y坐标反馈回来
那原因就是
在这样的非静态成员函数
都隐含着有一个this指针
那么比如说
我们调用一个getx函数的时候
貌似这个getx函数
它没有参数
参数表是空的
貌似我们的调用
没有给它传任何参数进去
但是实际上
暗地里传给它了一个东西
是什么
是当前这个对象的地址
你总要通过对象名.getx调用吧
这个对象的地址
就被传给getx函数了
那么这个getx函数内部呢
隐含的有一个指针
指针变量名叫做this
那么当前对象的地址
就传到this里面去了
所以在getx函数中
我们有return x这样一条语句
它就实际上相当于
return这个this
指针所指向对象的x
所以现在大家明白了吧
在此之前有的同学
已经有这样的疑问了
说为什么我进到getx函数里面
去以后
这个函数知道它从哪儿来的呢
知道是谁调用的它呢
按说进到函数体里头以后
这个函数是不知道
它的执行流程从哪儿进来的
不知道谁调用了它的
怎么它就那么巧
能把当前对象的这个x值
给返回呢
现在这个疑问解决了吧
大家还记得
在前面我们讲
前向引用声明的时候
给大家演示的那个错误的例子吧
好 现在呢
就给出正确的解决方案
这是我们在前面
讲前向引用声明的时候
出现过的例子
这个Barney类里面呢
有一个对象成员是Fred类对象
Fred类呢有个对象成员
是Barney类对象
结果把它们两个谁写前头
都不合适
用了前向引用声明
还是不解决问题
为什么呢
当你没有见到一个类的
完整定义的时候
是不能使用它的细节的
也就是说
不能去定义Fred类对象
编译器无法处理
不知道要给它多少字节的空间
至少这个细节信息是必须的
那这个没有
怎么办呢
现在我们可以变通一种做法
这个就是一个正确的解决方案
我们可以在Barney类里面
定义一个指向Fred对象的指针
那么只有一个指针
并没有Fred对象啊
没关系
你可以在构造函数中
在构造这个对象的时候
去用new运算做动态内存分配
分配一个Barney类的对象
将它的首地址赋给x这个指针
效果就达到了
就可以完成在Barney类里面
有Fred对象
在Fred类里面有Barney
对象的这样一个效果了
但是同学们肯定会觉得
我什么时候会需要这个效果呀
两个类对象
互相包含对方的子对象
其实有这样需求的时候其实很少
这个纯粹为了说明语法现象
这是一个验证性的例子
-导学
--第1章导学
-计算机系统简介
--计算机系统简介
--计算机系统简介 测试题
-计算机语言和程序设计方法的发展
--计算机语言和程序设计方法的发展 测试题
-面向对象的基本概念
--面向对象的基本概念 测试题
-程序的开发过程
--程序的开发过程
--程序的开发过程 测试题
-信息的表示和储存
--计算机的数字系统
--数据的编码表示
--信息的表示和储存 测试题
-实验指导
-导学
--第二章导学
-C++语言概述
--C++语言概述 测试题
-基本数据类型、常量、变量
--程序举例
--基本数据类型、常量、变量 测试题
-运算与表达式
--运算与表达式 测试题
-实验二:简单程序设计(上)
-数据的输入和输出
--数据的输入和输出
--数据的输入和输出 测试题
-选择结构
--if语句
--switch语句
--选择结构 测试题
-循环结构
--for语句
--循环结构 测试题
-自定义类型
--自定义类型
--自定义类型
-第2章小结
--第二章小结
-实验二:C++简单程序设计(下)
-导学
--导学
-函数定义
--函数定义
--函数定义 测试题
-函数调用
--例3-2
--例3-3
--例3-4
--例3-5
--例3-6
--函数调用 测试题
-嵌套与递归
--例3-9
--例3-10
--嵌套与递归 测试题
-函数的参数传递
--函数的参数传递
--函数的参数传递 测试题
-引用类型
--引用类型 测试题
-含有可变参数的函数
--含有可变参数的函数 测试题
-内联函数
--内联函数 测试题
-constexpr函数
--CONSTEXPR函数课后习题
-带默认参数值的函数
--带默认参数值的函数 测试题
-函数重载
--函数重载 测试题
-C++系统函数
--C++系统函数习题
-第3章小结
--第三章小结
-实验三(上)函数的应用
-实验三(下)函数的应用
-导学
--导学
-面向对象程序的基本特点
--面向对象程序的基本特点 测试题
-类和对象
--类和对象的定义
--类和对象 测试题
-构造函数
--构造函数基本概念
--委托构造函数
--复制构造函数
--构造函数 测试题
-析构函数
--析构函数
--析构函数 测试题
-类的组合
--类的组合
--类的组合程序举例
--前向引用声明
--类的组合 测试题
-UML简介
--UML简介
--UML简介课后习题
-结构体与联合体
--结构体与联合体 测试题
-枚举类
--枚举类
--枚举类 测试题
-第4章小结
--第四章小结
-实验四(上)
--实验四(上)
-实验四(下)
--实验四(下)
-导学
--导学
-标识符的作用域与可见性
--标识符的作用域与可见性 测试题
-对象的生存期
--对象的生存期
--对象的生存期 测试题
-类的静态成员
--类的静态成员 测试题
-类的友元
--类的友元 测试题
-共享数据的保护
--共享数据的保护 测试题
-多文件结构和预编译命令
--多文件结构和预编译命令 测试题
-第5章小结
--小结
-实验五
--实验五
-导学
--导学
-数组的定义与初始化
--数组的定义与使用
--一维数组应用举例
--数组的定义与初始化 测试题
-数组作为函数的参数
--数组作为函数的参数 测试题
-对象数组
--对象数组
--对象数组 测试题
-基于范围的for循环
-指针的定义和运算
--指针的定义和运算 测试题
-综合实例
--综合实例
-实验六(上)
--实验六上
-指针与数组
--指针数组
--指针与数组 测试题
-指针与函数
--指针类型的函数
--指向函数的指针
--指针与函数 测试题
-对象指针
--对象指针
--对象指针 测试题
-动态内存分配
--动态内存分配 测试题
-智能指针
--智能指针
-vector对象
--vector对象
--vector对象 测试题
-对象复制与移动
--移动构造
--对象复制与移动 测试题
-字符串
--C风格字符串
--string类
--字符串 测试题
-第6章小结
--第六章小结
-综合实例
--综合实例
-实验六(下)
--实验六(下)