第九十五天学习记录:C++核心:类和对象Ⅳ(五星重要)

news2024/9/30 15:22:41

C++对象模型和this指针

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

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

#include<iostream>
using namespace std;

class  Person
{
	int m_A;//非静态成员变量 属于类的对象上
	static int m_B;//静态成员变量 不属于类的对象上
	void func(){}//非静态成员函数 不属于类的对象上
	static void func2(){}//静态成员函数 不属于类的对象上
};

int Person::m_B = 100;

void test01()
{
	Person p;
	//空对象占用的内存空间为:1
	//C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
	//每个空对象也应该有一个独一无二的的内存地址
	cout << "size of p=" << sizeof(p) << endl;
}

void test02()
{
	Person p;//只有一个int类型的非静态成员变量时:4
	cout << "size of p=" << sizeof(p) << endl;
}

void test03()
{
	Person p;//有一个int类型的非静态成员变量和一个静态成员变量时:4
	cout << "size of p=" << sizeof(p) << endl;
}

void test04()
{
	Person p;//有一个int类型的非静态成员变量和一个静态成员变量和一个非静态成员函数时:4
	cout << "size of p=" << sizeof(p) << endl;
}

void test05()
{
	Person p;//4
	cout << "size of p=" << sizeof(p) << endl;
}

int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	test05();
	system("pause");
	return 0;
}

在这里插入图片描述

this指针概念

C++通过提供特殊的对象指针,this指针。this指针指向被调用的成员函数所属对象
this指针是隐含每一个非静态成员函数内的一种指针
this指针不需要定义,直接使用即可

this指针的用途:
1、当形参和成员变量同名时,可用this指针来区分
2、在类的非静态成员函数中返回对象本身,可以使用return *this;

#include<iostream>
using namespace std;
//1、解决名称冲突
class Person
{
public:
	Person(int age)
	{
		//this指针指向被调用的成员函数所属的对象
		this->age = age;
	}
	int age;

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

void test01()
{
	Person p1(18);
	cout << "p1的年龄为:" << p1.age << endl;
}

//2、返回对象本身用*this

void test02()
{
	Person p1(10);
	Person p2(10);
	p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
	cout << "p2的年龄为:" << p2.age << endl;
}

int main()
{
	test01();
	test02();
	return 0;
}

在这里插入图片描述

自行探索上述返回&类型

#include<iostream>
using namespace std;

int& test02(int &num)
{
	num++;
	cout << "&num=" << &num << endl;
	return num;
}

int main()
{
	int b = 10;
	cout << "&b=" << &b << endl;
	cout << "&b=" << &(test02(b)) << endl;
	int* ret=&(test02(b));
	cout << "ret=" << ret << endl;
	return 0;
}

通过上述代码输出结果得出:
在这里插入图片描述
所有地址都是一样的。
但如果将int& test02(int &num)改成int test02(int &num)的话,代码会报错。因为这样函数返回的int值必须得新建一个int类型的变量来接收之后才可以取地址。
不过这里也能够确定返回不加引用的int的地址肯定不能是之前的地址。
那么问题来了,为什么将:

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

更改成

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

之后不会报错呢?
只是这样更改后输出p2的年龄不是40而是20

先把代码改写成这样:
1、增加了几句输出
2、手动增加了拷贝构造函数

#include<iostream>
using namespace std;
//1、解决名称冲突
class Person
{
public:
	Person(int age)
	{
		//this指针指向被调用的成员函数所属的对象
		cout << "initthis=" << this << endl;
		this->age = age;
	}
	int age;

	Person(const Person &p)
	{
		age = p.age;
		cout << "Person的拷贝数构造函数调用" << endl;
	}

	Person& PersonAddAge(Person &p)
	{
		cout << "addthis=" << this << endl;
		this->age += p.age;
		return *this;
	}
};

void test01()
{
	Person p1(18);
	cout << "p1的年龄为:" << p1.age << endl;
}

//2、返回对象本身用*this

void test02()
{
	Person p1(10);
	Person p2(10);
	p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
	cout << "p2的年龄为:" << p2.age << endl;
}

int main()
{
	//test01();
	test02();
	return 0;
}

输出得到:
在这里插入图片描述
可见,p2的this一直是0075FC1C
但是如果把Person& PersonAddAge(Person &p)改成Person PersonAddAge(Person &p)
输出如下:
在这里插入图片描述
在其返回Person类型的时候,调用了拷贝构造函数,相当于下一次进行该函数的时候已经是另一个对象了。
我们可以再添加一些输出来观察this->age的变化。

	Person PersonAddAge(Person &p)
	{
		cout << "addthis=" << this << endl;
		cout << "this->ageb=" << this->age << endl;
		this->age += p.age;
		cout << "this->agea=" << this->age << endl;
		return *this;
	}

在这里插入图片描述
可以看到,虽然this->age的值最终达到了40,但是由于最终的输出结果是p2.age,而p2的地址是00CFF9B0。因此p2.age=20。

空指针访问成员函数

C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针
如果用到this指针,需要加以判断保证代码的健壮性

#include<iostream>
using namespace std;

class Person
{
public:
	void showClassName()
	{
		cout << "this is Person class" << endl;
	}
	void showPersonAge()
	{
		//报错的原因是因为传入的指针是NULL
		//if (this == NULL)
		//{
		//	return;
		//}//建议加上这几行代码加以保护
		cout << "age=" << m_Age << endl;
	}
	int m_Age;
};

void test01()
{
	Person* p = NULL;
	p->showClassName();
	//p->showPersonAge();//会崩
}

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

const修饰成员函数

常函数:
1、成员函数后加const后我们称为这个函数为常函数
2、常函数内不可以修改成员属性
3、成员属性声明时加关键字mutable后,在常函数中依然可以修改

常对象:
1、声明对象前加const称该对象为常对象
2、常对象只能调用常函数

#include<iostream>
using namespace std;

class Person
{
public:
	//this指针的本质是常量指针 指针的指向是不可用修改的
	//const Person* const this
	//在成员函数后面加const,修饰的是this指向,让指针指向的值也不可以修改
	void showPerson()const
	{
		//m_A = 100;//报错
		//this=NULL;//this指针不可以修改指针的指向
		this->m_B;//加了关键字mutable就可以修改
	}
	void func()
	{

	}

	int m_A;
	mutable int m_B;
};

void test01()
{
	Person p;
	p.showPerson;
}



void test02()
{
	const Person p;//在对象前加const,变为常对象
	//p.m_A = 10;//报错
	p.m_B = 100;//可修改,在常对象下也可以修改
	p.showPerson();
	//p.func();//报错 常对象 不可以调用普通成员函数,因为普通成员函数可以修改属性


	//常对象只能调用常函数
}

int main()
{
	test01(); 
	test02();
	return 0;
}

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

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

相关文章

Gradio库的Gallery模块介绍与select方法详解

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Flask boostrap实现图片视频上传下载展示

Flask boostrap实现图片视频上传下载展示 1、展示效果2、前端代码3、后端代码 1、展示效果 项目目录结构 2、前端代码 html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title>&l…

Go 程序是怎样跑起来的

Go 程序是怎样跑起来的 引入 我们从一个 helloworld 的例子开始 package mainimport "fmt"func main() {fmt.Println("hello world") }用 vim 要打开&#xff0c;输入命令&#xff1a; :%!xxd下面是输出 00000000:7061 636b 6167 6520 6d61 696e 0a0a…

tomcat概述,优化,多实例部署

目录 一、概述 二、三个容器 1、Web 容器&#xff1a; 2、Servlet 容器&#xff1a; 3、JSP 容器&#xff1a; 三、Tomcat 功能组件结构 四、优化 1、启动速度优化 2、配置参数优化 五、多实例部署 一、概述 Tomcat 是 Java 语言开发的&#xff0c;Tomcat 服务器是一…

ubuntu下安装docker遇到的问题

如果你还没有安装虚拟机&#xff0c;推荐一篇关于安装Ubuntu的详细教程&#xff1a; VMware虚拟机安装Ubuntu20.04详细图文教程https://blog.csdn.net/weixin_41805734/article/details/120698714首先&#xff0c;安装docker的前提是虚拟机能够联网&#xff0c;如果能看到右上…

官方文档中docker安装php插件xdebug

docker安装php插件 直接上代码常见问题如果查看系统类型如何查看xdebug合适的版本安装异常提示Cannot find autoconf. Please check your autoconf installation and the$PHP_AUTOCONF environment variable. Then, rerun this script.configure: error: in /tmp/pear/temp/pea…

Zookeeper 分布式锁

优质博文&#xff1a;IT-BLOG-CN 一、简介 随着公司业务的发展&#xff0c;单机应用已经无法支撑现有的用户量&#xff0c;之前采用synchronized和Lock锁已经无法满足分布式系统的要求。我们应用程序目前都会运行120台&#xff0c;节假日会扩容至240台&#xff0c;属于多JVM环…

领域事件驱动(二)聚合与聚合根的了解

上一章对值对象以及实体进行了一些简单的讲解&#xff1a; 聚合 聚合&#xff1a;我们把一些关联性极强、生命周期一致的实体、值对象放到一个聚合里。 聚合有一个聚合根和上下文边界&#xff0c;这个边界根据业务单一职责和高内聚原则&#xff0c;定义了聚合内部应该包含哪…

U-Boot移植 - 2_环境搭建和u-boot烧录启动

文章目录 1. 编译环境搭建1.1 交叉编译器下载1.2 交叉编译器安装 2. 编译原厂uboot3. 烧录开发板3.1 烧录到SD卡3.2 启动开发板 1. 编译环境搭建 1.1 交叉编译器下载 嵌入式Linux开发&#xff0c;程序编译通常在电脑端的Linux&#xff08;如虚拟机中的Ubuntu)下进行编译&…

阿里云ECS部署

nginx 安装nginx # 查看dnf版本 dnf --version# 查找是否是否安装 dnf search nginx# 安装nginx dnf install nginx# 启动nginx systemctl start nginx# 查看nginx运行状态 systemctl status nginx# 相当于开机自启&#xff08;重启服务器&#xff0c;nginx自动启动&#xff…

GoLand下载、安装

一、Goland下载 官方最新版本下载地址&#xff1a; Download GoLand: A Go IDE with extended support for JavaScript, TypeScript, and databases 其他版本下载&#xff1a; Other Versions - GoLand 二、安装过程 1.下载好goland-2021.1.1安装包后&#xff0c;双击运行安装包…

【ARIMA-WOA-CNN-LSTM】合差分自回归移动平均方法-鲸鱼优化-卷积神经网络-长短期记忆神经网络研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Redis主从复制模式4

哨兵模式 有个哨兵一直在巡逻&#xff0c;突然发现。老大挂了&#xff0c;小弟们会自动投票&#xff0c;从众小弟中选出新的老大。即自动版的谋权篡位。我们把这个过程称为哨兵模式 设置哨兵模式语法格式&#xff1a; sentinel monitor 被监控主机名/IP Redis服务端口 票数 关闭…

AutoCV第十一课:DL基础

目录 DL基础前言1. BP训练mnist2. 权重初始化理论分析总结 DL基础 前言 手写AI推出的全新保姆级从零手写自动驾驶CV课程&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考。 本次课程我们来了解下 BP 反向传播和学习权重初始化相关知识 课程大纲可看下面的思维导…

java新特性stream

stream Java 8 是一个非常成功的版本&#xff0c;这个版本新增的Stream&#xff0c;配合同版本出现的 Lambda &#xff0c;给我们操作集合&#xff08;Collection&#xff09;提供了极大的便利。 Stream将要处理的元素集合看作一种流&#xff0c;在流的过程中&#xff0c;借助…

PMP常用英文术语缩写总结(文字版+表格版+图片版)

PMP常用英文术语缩写总结&#xff08;文字版表格版图片版&#xff09; 文字版 PMBOK Project Management Body of Knowledge 项目管理知识体系 PMI Project Management Institute 项目管理协会 PMO Project Management Office 项目管理办公室 PMIS Project Management Inf…

Spring Boot 中的服务注册是什么,原理,如何使用

Spring Boot 中的服务注册是什么&#xff0c;原理&#xff0c;如何使用 Spring Boot 是一个非常流行的 Java 后端框架&#xff0c;它提供了许多便捷的功能和工具&#xff0c;使得开发者可以更加高效地开发微服务应用。其中&#xff0c;服务注册是 Spring Boot 微服务架构中非常…

代码源 线段树模板

线段树1 思路&#xff1a; 我们需要维护的东西是序列的最小值和最小值个数 这道题没有修改操作&#xff0c;因此不考虑修改 然后考虑Pushup 最小值很简单&#xff0c;直接取min 最小值个数怎么维护呢&#xff1f;考虑这个区间需要维护的值如何从左右两个区间获得 如果左右…

四.流程控制语句

1、条件语句 Go 编程语言中 if 条件语句的语法如下&#xff1a; 1、基本形式 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } If 在布尔表达式为 true 时&#xff0c;其后紧跟的语句块执行&#xff0c;如果false 则不执行。 package main import "fmt" fu…