C++:类和对象:C++对象模型和 this指针

news2024/11/14 15:15:19

1:成员变量和成员函数分开存储

在C++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类对象。

案例:我们写一个空类,然后创建一个对象,看看这个空对象占用多大空间。

#include<iostream>
#include<string>
using namespace std;
class Person {

};

void test() {
	Person p;
	cout << "size of p is: " << sizeof(p) << endl;
}

int main() {
	test();
	return 0;
}

 运行结果可知:

   空对象大小为1字节,这是因为编译器为了区分空对象占用内存位置,给每个空对象也会分配一个独一无二的内存地址。

 案例:我们写在这个类中添加一个  int 类型的成员变量 m_A。

#include <iostream>
using namespace std;
#include <string>

class Person
{
	int m_A;
};

void test01()
{
	Person p;
	cout << "size of p is: " << sizeof(p) << endl;
}

int main()
{
	test01();

	return 0;
}

 运行结果可知:

包含一个int类型成员变量,这个对象的大小是 4字节。

 当我们增加静态成员变量,静态成员函数,非静态成员函数时。

#include<iostream>
#include<string>
using namespace std;
class Person {
	int m_A;
	static int m_B;
	static void func() {};
	void func1() {};
};

void test() {
	Person p;
	cout << "size of p is: " << sizeof(p) << endl;
}

int main() {
	test();
	return 0;
}

 运行结果可知:

      不管是静态成员函数,成员韩式,静态成员变量,均不会增加这个对象所占内存大小。

2:this指针 

问题

Question :  在C++ 中成员变量和成员函数是分开存储的,每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会公用一块代码,那么问题是:这一块代码是如何区分到底哪个对象调用自己的了 ?

Answer:   C++通过提供特殊的对象指针(this指针)来解决上述问题。this指针指向被调用的成员函数所属的对象。 this指针是隐含每一个非静态成员函数的一种指针。 this指针不需要定义,可以直接使用。

this指针用途:

-------》当形参和成员变量同名时,可用this指针来区分。

-------》在类的非静态成员函数中返回对象本身,可使用  return *this 。

案例:现在我们想增加一个成员函数,实现将一个对象的年龄加到另一个对象的年龄上。 

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	Person(int age) {
		// 1:当形参和成员变量同名时,可用 this指针加以区分。
		this->age = age;
	}

	Person& PersonAddPerson(Person& p) {
		this->age += age;
		return *this;
	}

	int age;
};

void test() {
	Person p1(10);
	cout << "p1.age = " << p1.age << endl;
	Person p2(10);
	p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);
	cout << "p2.age = " << p2.age << endl;
}

int main() {
	test();
	return 0;
}

运行结果可知:由于每次执行 PersonAddPerson()函数都能返回当前对象,所以可以实现当前对象p2(age的累加)。 

3:空指针访问成员函数

在C++中空指针也是可以调用成员函数的,但是也需要注意是否使用到 this指针,如果用到 this指针,那么我们就需要添加判断保证代码的健壮性。

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	
	void ShowPerson() {
		cout << "showPerson enter" << endl;
	}

	int age;
};

void test() {
	// Null空指针是可以调用成员函数的
	Person* p = NULL;
	p->ShowPerson();
}

int main() {
	test();
	return 0;
}

如果:成员函数中用到了 this指针,就是不可以的,就需要对this进行判断。

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	
	void ShowPerson() {
		// 事实上属性的前面都是默认添加了 this , 即等同于 this.age 。
		if (this == NULL)
		{
			cout << "当前 person对象为空" << endl;
		}
		else
		{
			cout << age << endl;
		}
	}

	int age;
};

void test() {
	// Null空指针是可以调用成员函数的,但是一旦成员函数使用了 this 就是不可以的
	Person* p = NULL;
	p->ShowPerson();
}

int main() {
	test();
	return 0;
}

4:const修饰成员函数、修饰对象

常函数:

1:  成员函数后加 const,我们称这个函数为  常函数。

2:常函数内不可以修改成员属性。

3:但是成员属性声明时加关键字 mutable ,那么在常函数中依然可以修改。

案例:常函数无法修改普通的成员变量,但是可以修改 mutable修饰的成员变量 。

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	
	/**
		this 指针的本质时一个 指针常量 Person* const this,指针的指向不可以修改,但是指向的值可以修改
		如果想让指针指向的值也不可修改,那么就需要声明为 常函数,在函数的参数列表后添加 const
		这样 this 指针就变成 :  const Person* const this
	
	*/
	void ShowPerson() const {
		// this = NULL; // 不能修改指针的指向
		// this->m_A = 100; //指针this指向的对象的数据也不能修改。
		this->m_B = 100; // mutable修饰的变量时可以修改的。
	}

	int m_A;
	mutable int m_B;
};


int main() {
	
	return 0;
}

常对象:

1:声明对象前 添加 const,那么称该对象为 常对象,常对象无法修改成员变量的值

2:如果成员变量添加了 mutable ,那么常对象可以修改这个成员变量的值

3:常对象只能调用常函数,因为普通函数可能会修改 成员变量的值

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	// 常函数
	void MyFunc()const {}
	// 普通函数
	void MyFunc2() {}
	// 普通变量
	int m_A;
	// mutable 可变变量
	mutable int m_B;
};


int main() {
	const Person person; // 常量对象
	person.MyFunc(); // 常量对象只能调用常量函数
	person.m_A = 100; // 常量对象不能修改普通成员变量
	person.m_B = 100; // 常量对象可以修改 mutable修饰的成员变量
	person.MyFunc2(); // 常量对象也不能调用普通函数
	return 0;
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

做全表扫描时数据表的内存大于 MySQL 内存,会不会被打爆?

我查这么多数据&#xff0c;会不会把数据库内存打爆&#xff1f; 我的数据库内存只有10G&#xff0c;现在我要对一个20G的大表做全表扫描&#xff0c;会不会把数据库内存&#xff08;buffer pool&#xff09;占满然后报OOM的错误&#xff1f; 答案是不会的。 InnoDB的数据是…

【图像处理 -1图像恢复】非线性过滤器修复图像

【论文参考】文章地址&#xff1a; https://www.researchgate.net/publication/303996052_Image_Restoration_Technique_with_Non_Linear_Filter Image Restoration 一、摘要 在本文中&#xff0c;提出了一种新的处理方法图像使用不同的过滤方法 实现Image恢复。目的是增强数…

计算机网络原理第4章 网络层

目录~ 4.1 网络层提供的两种服务 面向连接&#xff1a;让网络负责可靠交付&#xff0c;通信之前先建立虚电路 无连接&#xff1a;网络提供数据报服务&#xff0c;网络层提供简单灵活的、无连接的、尽最大努力交付的数据报服务 4.2 网际协议 IP 网际协议 IP 是 TCP/IP 体系…

基于JAVA的校友录

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 网站前台&#xff1a;关于我们、联系我们、校园通知、组织信息、活动信息 管理员功能&#xff1a; 1、管理关于我们、联…

java方法耗时统计,JavaAgent javassist bytebuddy统计方法耗时,jvm监控prometheus

前言介绍 JavaAgent是在JDK5之后提供的新特性&#xff0c;又叫叫java代理。开发人员可通过这种机制(Instrumentation)在jvm加载class文件之前修改类的字节码&#xff0c;动态更改类方法实现AOP&#xff0c;提供监控服务如&#xff1a;方法调用时长、jvm内存等。修改字节码领域…

jsp+ssm计算机毕业设计大学生校园新闻发布系统【附源码】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JSPSSM mybatis Maven等等组成&#xff0c;B/S模式 Mave…

色温及其相关参数

光学膜层和大多数着色表面不是自发光的。为了看到它们&#xff0c;我们需要一个光源。显然&#xff0c;对颜色的任何评估都将包括光源的属性。在计算颜色时&#xff0c;我们通常使用标准光源&#xff0c;其中大部分是由CIE根据其相对光谱输出来定义的&#xff0c;并且尽可能地表…

java计算机毕业设计springboot+vue在线选课系统

项目介绍 本系统是针对目前在线选课系统管理的实际需求,从实际工作出发,对过去的在线选课系统系统存在的问题进行分析,完善用户的使用体会。采用计算机系统来管理信息,取代人工管理模式,查询便利,信息准确率高,节省了开支,提高了工作的效率。 本系统结合计算机系统的结构、概…

ARM寻址方式(ARM指令获取操作数的方式)

所谓寻址方式&#xff0c;指的是CPU去获取一个操作数的方式&#xff0c;可以是从指令中获取立即数、可以是从寄存器中获取&#xff0c;也可以是从内存中获取。 目录 1、立即数寻址 2、寄存器寻址 3、寄存器移位寻址 4、寄存器间接寻址 5、基址加变址寻址 (1) 前向索引…

springboot-mybatis/JPA流式查询

项目中有几个batch需要检查所有的用户参与的活动的状态&#xff0c;以前是使用分页&#xff0c;一页一页的查出来到内存再处理&#xff0c;但是随着数据量的增加&#xff0c;效率越来越低。于是经过一顿搜索&#xff0c;了解到流式查询这么个东西&#xff0c;不了解不知道&…

计算机毕业设计springboot+vue基本微信小程序的演出门票管理系统-票务转票系统

项目介绍 转票是一个传统的行业。根据当前发展现状,网络信息时代的全面普及,转票也在发生着变化,单就出票这一方面,利用手机预约考试正在逐步进入人们的生活。传统的转票方式,不仅会耗费大量的人力、时间,有时候还会出错。小程序系统伴随智能手机为我们提供了新的方向。手机微信…

新兴物种:程序猿的饲养指南

程序猿&#xff0c;一种主要生存在中国印度等亚太国家的新型猿类&#xff0c;生存活动以及消费活动的范围遍布世界各地&#xff0c;其中最优渥的产地位于美国硅谷。 主要的生存环境需求有&#xff0c;两脚兽一切的日用饮食以及物资需求。 该物种所获得的荣誉勋章有&#xff0…

Spring系列之SpringBoot概述及入门

SpringBoot入门 文章目录SpringBoot入门一、SpringBoot是什么&#xff1f;二、Spring的缺点1.配置繁琐2.依赖繁琐三、SpringBoot功能四、SpringBoot起步依赖原理五、SpringBoot快速入门总结一、SpringBoot是什么&#xff1f; SpringBoot是由Pivotal团队提供的全新框架&#xf…

Splunk Enterprise 9.0.X Crack

Splunk Enterprise 9.0.X Crack Splunk 有能力了解用户小型企业中实际发生的情况&#xff0c;并快速采取有目的的行动来了解用户和开发人员的情况。它能够轻松灵活地将简单信息转化为答案&#xff0c;以及自动机器学习支持的分析过程 搜索、分析和可视化&#xff0c;从您的所…

基于springcloud的简单易用的java分布式日志组件

真正的大师,永远都怀着一颗学徒的心&#xff01; 一、项目简介 基于springcloud的简单易用的java分布式日志组件 二、实现功能 支持基于traceId的日志记录 支持日志查询 支持日志缓冲队列 redis或者kafka 支持错误报警模块 支持内容组合查询功能 支持日志分应用统计条数…

【神奇bug】“金”、“⾦”不是同一个字

身为程序员&#xff0c;总能遇见那些神奇的bug。我前段时间遇到了 “中国黄金” 和 “中国黄⾦”&#xff0c;我咋看咋觉得是同一个词&#xff0c;但是程序就是判定不一致&#xff0c;十分郁闷&#xff0c;多方搜索&#xff0c;最后发现2个金居然不是一个字。真是个神奇的bug&a…

计算机基础学习笔记:操作系统篇之硬件结构,CPU Cache基础概念

三、CPU Cache的数据结构和读取过程 本文知识来源小林Coding阅读整理思考&#xff0c;原文链接请见该篇文章 Cache结构 CPU Cache 是由很多个 Cache Line 组成的&#xff0c;Cache Line 是 CPU 从内存读取数据的基本单位&#xff0c;而 Cache Line 是由各种**标志&#xff08;…

基于java+springmvc+mybatis+vue+mysql的智能新冠疫苗接种助手

项目介绍 随着全球新冠疫情的蔓延&#xff0c;基本所有的发达国家都开始了全民疫苗接种的行为&#xff0c;在我国更是进行了全民的新冠疫苗接种&#xff0c;为了能够让民众更加方便快捷的进行疫苗的接种我们通过java编程语言&#xff0c;后端ssm框架&#xff0c;前端vue技术开…

【Python百日进阶-数据分析】Day129 - plotly柱状图(条形图):px.bar()实例

文章目录四、实例4.1 Plotly Express条形图4.1.1 加拿大人口4.1.2 一维数据的条形图4.1.3 多维数据条形图4.1.4 彩条4.1.5 堆叠与分组条形图4.1.6 聚集成单色条4.1.7 带文本的条形图4.1.8 填充图案4.1.9 分面子图4.1.10 带Plotly Express的基本水平条形图4.1.11 配置水平条形图…

nacos服务注册与发现

目录 1. 应用系统架构的演变&#xff08;单应用>分布式&#xff09; 2. Spring Cloud Alibaba介绍 3. 开发示例 3.1 版本的选择 3.2 nacos安装 3.3 创建工程 3.3.1 创建父工程 3.3.2 创建服务提供者模块 3.3.2 服务消费者 3.4 测试 今天与大家们简单的聊一下&#…