(30.2)对象数组以及指向对象的指针

本文深入解析C++中的类成员指针、数据成员指针、成员函数指针及其应用,同时详细阐述了this指针的概念、作用及应用场景,帮助读者理解并掌握C++中复杂指针的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
  • eg:
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是调用对象的地址

  • eg
#include <iostream>
#include <string.h>
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;
};
  • this指针的const限定
(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指向的内容。
### Jmol 版本 14.30.2 发布说明及相关特性 Jmol 是一种用于显示三维化学结构的开源软件工具。以下是关于 Jmol 14.30.2 版本的一些重要发布说明和新增功能: #### 主要更新内容 - **性能改进**: 此版本显著提升了渲染速度以及内存管理效率,尤其是在处理大型分子模型时表现更为突出[^1]。 - **新支持文件格式**: 增加了对几种新型生物信息学数据格式的支持,例如 mmCIF 和 PDBx 扩展版,这使得研究人员能够更方便地加载最新的蛋白质数据库记录。 - **增强交互体验**: 用户界面经过优化调整,默认行为更加直观合理;同时修复了一些长期存在的 bug,比如拖拽旋转过程中偶尔发生的卡顿现象。 #### JavaScript API 变化 对于开发者而言,在该版本中也引入了几项值得注意的变化: - `getVersion` 方法现在除了返回字符串形式的版本号外,还额外提供了一个对象参数来描述详细的构建日期和其他元数据信息: ```javascript var versionInfo = Jmol.getVersion(myJmol); console.log(versionInfo.fullString); // 输出完整的版本信息串 ``` - 关于动态尺寸调节方面,虽然原有的 `resizeApplet` 函数仍然可用,但推荐采用新的响应式布局方案——通过 CSS Flexbox 或 Grid 实现自适应窗口大小变化的效果: ```css /* 示例CSS代码 */ .jmol-container { display: flex; justify-content: center; align-items: center; width: 80vw; /* 占据视口宽度的80% */ height: auto; } ``` 以上就是针对 Jmol Version 14.30.2 的一些关键改动概述。更多细节可以查阅官方文档或者源码仓库中的 CHANGELOG 文件获取全面的信息。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜欢打篮球的普通人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值