C++ this指针与静态属性的关系

关于静态的说明:

1.类中的静态成员是所有对象共享的,所以不能在静态方法里面访问非静态元素
2.类中的非静态成员,可以访问类的静态成员和类的非静态成员


C++内存的分配方式

要想理解this指针和静态属性的关系,需要先了解C++内存的分配方式

一个由C/C++编译程序占用内存分为以下几个部分:

栈区(stack) : 由编译器自动分配和释放,存放 函数参数值,局部变量值,返回地址等。操作方式类似于数据结构中的 栈 。栈内存分配时的运算 内置于处理器指令集中, 效率很高但分配内存的容量有限(VC6下,默认的栈空间大小为1M)

堆区(heap) : 一般 由程序员进行分配和释放 ,亦称动态的内存分配,如果程序员不进行释放,程序结束时可能由OS回收,程序在运行时用mallocnew申请任意多少的内存,程序员自己负责在何时用freedelete释放内存。 动态内存生存周期由我们决定,使用非常灵活但问题繁多 ,与数据结构中的 堆 是两个概念,分配方式类似于链表(32位系统下,堆内存空间可以达到4G)

全局区(静态区)(static) : 全局变量和静态变量存储是存放在一块的,初始化过的全局变量和静态变量为一个区域,未进行初始化的全局变量和静态变量在另一块相邻的区域.全局区的内存在程序结束后由系统释放 (初始化过的变量释放到data区,未初始化的变量分配到bbs区)

文字常量区 : 常量字符串就是放在这里,程序结束后由系统释放到coment区

程序代码区 : 存放函数体二进制代码,存放在code区


this指针

回顾一下什么是this指针:
this指针是类的一个自动生成的并自动隐藏私有成员(privite),它存在于类的非静态成员函数,this指针指向被调用函数所在的对象的地址

也就是说,当一个对象被创建,该对象内便会自动生成一个this指针成员,其为私有成员且自动隐藏,生成后便自动指向对象数据的首地址


为了证明this指针是指向对象数据的首地址,用以下程序进行说明

#include <iostream>
#include <string>

using namespace std;

class Point
{
private:
	static int count;//todo定义访问权限为私有的静态变量count
	int x, y;
	static int staticnum;//类内声明静态变量
public:
	Point(int a, int b)//todo构造函数
	{
		count++;//todo每构建一个对象就会调用构造函数,count这个静态变量也会自增
		cout<<"第"<<count<<"个对象的this指针地址为" << this << endl;//todo打印this指针(对象的地址 只能放入类和类的成员函数中) 
		x = a;
		y = b;
	}
	void MovePoint(int a, int b)
	{
		x = a;
		y = b;
	}
	void print()
	{	
		cout << "x为:" << x << "          y为:" << y << endl;
	}
};
//🌟类外声明静态变量 (要使用静态变量和静态成员函数 必须分配内存和初始化)
int Point::count = 0;
int Point::staticnum=0;

int main()
{	
	
	Point point1(10, 10);
	point1.print();
	cout << "对象的地址为" <<&point1 << endl;//todo打印对象的地址
	point1.MovePoint(2, 2);
	//todo当对象point1调用Movepoint(2,2)这个函数时,即将point1对象的地址传递给了this指针
	//Movepoint(2,2)这个函数的原型应该是void Movepoint(Point this*,int a,int b);
	//todo第一个参数时指向该类对象的一个指针,我们在定义成员函数时没看见是因为这个参数在类中是隐含的
	//这样point1的地址传递给了this指针,所以在MovePoint函数中便可以显示的写成:void MovePoint(int a,int b){this->x=a;this->y=b;}
	//todo即可知道,point1调用该函数后,也就是point1的数据成员被调用并更新了值

	point1.print();


	//todo在任何一个方法里都可以使用this指针。C++对象是一种特殊的结构 是除了变量还包含一些函数的特殊结构
	//程序运行时,对象的属性(变量)和方法(函数)都是保存在内存里,这就意味着它们各自都有与之相关联的地址
	//todo这些地址都可以通过指针来进行访问,而this指针一定保存着对象本身的地址,每调用一个方法,this指针都会随着提供的输入参数被秘密的传递给那个方法
	//正是因为如此,我们才能在方法里像使用一个布局变量那样使用this指针

	//todo因为静态成员和静态方法不是属于某个特定的对象,而是由全体对象共享的,这就意味着它们无法访问this指针,所以,我们才无法在静态方法里访问非静态的类成员(变量和方法)
	//如果需要访问非静态的类成员 则需要this指针来访问 
	//todo在使用静态属性时,必须为它们分配内存。具体做法很简单,只要在类声明的外部对静态属性进行声明即可(类似于声明一个变量)
	
	Point point2(20, 20);
	point2.print();
	return 0;
}

当对象point1调用MovePoint(2,2)函数时,此时point对象的地址也传递给你了this这个指针,MovePoint函数的原型事实上应是:

void MovePoint(Point *this, int a, int b);

参数列表中的第一个参数是指向该类对象的一个指针,我们在定义成员函数时没看见是因为这个参数在类中是隐含的,此时,point1的地址传递给了this,所以在MovePoint函数中便可以显式的写成:

void MovePoint(int a,int b)
{
	this->x=a;//此行意思为 point1这个对象的地址中的x的值 赋值给movePoint中的a
	this->y=b;
}

即可以知道,point1调用该函数后,也就是point1的数据成员被调用(调用值-类成员x,y) 并 更新了值(更新值-MovePoint函数中的a,b)


程序结果:

在这里插入图片描述


总结和注意:🎯

任何一个方法(包括构造器函数)都可以使用this指针获取对象的地址,从本质上讲,C++中的对象其实是一种特殊的结构(是一种除了变量还包含函数的特殊的结构)

在程序正在运行时,对象的属性(变量)和方法(函数)都是保存在内存中,且各自都有与之相关联的地址,这些地址都可以通过指针来进行访问,而最重要的this指针保存着对象本身的地址

每调用一个方法的时候,this指针都会随着你提供的输入参数被秘密的传递给这个方法,正因为如此,我们才能在方法(成员函数)里像使用一个局部变量那样使用this指针

由于静态方法不是属于某个特定的对象,而是由全体对象共享,这就意味静态方法不可能有个固定的地址来索引某个对象,也就是说静态方法无法访问this指针,而非静态成员需要用this指针来访问自己属于的对象,这就是为什么我们无法在静态方法里访问非静态成员的原因


本文来自
C++内存分配方式详解🔍
静态属性和静态方法2以及this指针的又一些说明🔍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值