类和对象【1】

news2024/11/27 8:46:10

全文目录

  • 引言(初识面向对象)
  • 类和对象
    • 定义
      • 类访问限定及封装
      • 类定义的两种方式
    • 类实例化与类对象大小
    • this指针
  • 总结

引言(初识面向对象)

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题;
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

比如洗衣服这个操作,对于面向过程的C语言而言,就是要根据洗衣服的过程按照逻辑逐步依次实现:
在这里插入图片描述
最多将放洗衣液的多个步骤封装一个函数,进行多遍的冲洗操作写一个循环。总之面向的是洗衣服的过程。

但对于面向对象的C++而言,洗衣服的过程就可以按照封装的几个对象之间的交互实现。比如分为人、衣服、洗衣液与洗衣机:
在这里插入图片描述
洗衣服只需要人将衣服与洗衣液放到洗衣机中,由洗衣机执行操作即可。有些洗衣机对象还可以实现自动加洗衣液,此时洗衣液就是洗衣机的一个内部对象。总之面向的是洗衣服时参与到的对象。

不难发现,面向对象的操作过程是要比面向过程的操作过程简单高效的。也就是说,面向对象编程是一种相对高级的编程方式。

类和对象

C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数:

struct Stack
{
	int* _data;
	int _top;
	int _capacity;

	void init();	
	void push();
	void pop();
	void destory();
};

在C语言中实现的栈,结构体中只有变量,是通过函数来操作结构体中的变量;而C++的栈结构体中可以定义函数,这其实就是一个类。struct可以用来定义类,在C++中有一个专门的关键字class来定义类:

定义

class定义类的格式如下:

class Classname
{
	//类的主体(成员变量与成员函数)
};

class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。

类访问限定及封装

用类将对象的属性与方法结合到一起就是封装,并且通过访问限定隐藏属性以及方法的细节,只向用户提供接口,使用户更方便的使用类:

有三种访问限定符:public(公有)、protected(保护)、private(私有):

class Classname
{
public:
	//公共权限:类内可以访问,类外可以访问;
protected:
	//保护权限:类内可以访问,类外不可以访问(子类可以访问);
private:
	//私有权限:类内可以访问,类外不可以访问(子类不可以访问);
};

不难发现,由于类需要向用户提供接口,而隐藏属性,所以类的成员函数一般都是放在公有域,成员变量都放在私有域。

需要注意的是:

  1. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止, 如果后面没有访问限定符,作用域就到 } ,即类结束
  2. class的默认访问权限为private,struct为public(因为struct要兼容C)。

类定义的两种方式

定义类时,可以有两种方式:函数的声明与定义在一起放在类中或者函数的声明与定义分离,声明放在类中,函数定义放在.cpp文件中:

需要注意的是,如果在类中定义成员函数,这个函数会被默认当成内联函数(这里简单写一个日期类例举):

class Date
{
public:

	void InitDate(int year = 2023, int month = 2, int day = 10)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date& AddDate(int day)
	{
		_day += day;
		while (_day > GetMonthDay(_year, _month))
		{
			_day -= GetMonthDay(_year, _month);
			_month++;
			if (_month > 12)
			{
				_year++;
				_month = 1;
			}
		}
		return *this;
	}
	int GetMonthDay(int year, int month)
	{
		int monthdays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if ((month == 2) && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			monthdays[month] = 29;
		}
		return monthdays[month];
	}
private:
	int _year;
	int _month;
	int _day;
};

如果声明和定义分离,在定义函数时需要类名::函数名的方式定义:

class Date
{
public:
    void InitDate(int year = 2023, int month = 2, int day = 10);
	Date& AddDate(int day);
	int GetMonthDay(int year, int month);
private:
	int _year;
	int _month;
	int _day;
};

void Date::InitDate(int year = 2023, int month = 2, int day = 10)
{
	_year = year;
	_month = month;
	_day = day;
}
Date& Date::AddDate(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		_month++;
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}
	}
	return *this;
}
int Date::GetMonthDay(int year, int month)
{
	int monthdays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	if ((month == 2) && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	{
		monthdays[month] = 29;
	}
	return monthdays[month];
}

在定义类时,建议使用第二种方式,并且将公有的成员函数定义在私有的成员变量之前

类实例化与类对象大小

在上面定义的类只是一种类类型,相当于房子的图纸,并不在内存中开辟空间。
用类创建对象的过程称为类的实例化,实例化的对象占有具体的内存空间。
类名就是类类型的类型名,一个类类型可以实例化多个类对象,比如上面的日期类:

int main()
{
    //实例化三个类对象
	Date d1;
	Date d2;
	Date d3;
	//对三个类对象调用其成员函数进行初始化
	d1.InitDate();
	d2.InitDate(2023, 5, 14);
	d3.InitDate(2000, 1, 1);
	return 0;
}

上面的内容并不难理解,但是由于成员函数也是包含在类对象中的,类的大小应该如何计算?
在C语言部分,我们了解了如何计算结构体的大小,结构体在内存分配时遵循内存对齐的规则:
戳我看结构体内存对齐详解哦

类的大小也遵循内存对齐的规则,但是对于成员函数,它虽然封装在类中,但是却不占用类对象的空间。成员函数的只保存一份在代码段,类对象中只保存成员变量

int main()
{
	Date d1;
	cout << sizeof(d1) << endl;
	return 0;
}

在这里插入图片描述
所以对于上述Date类对象d1的大小只包括三个int型的成员变量,根据内存对齐,大小就是12字节。

对于空类,会有一个字节的空间以区分。

this指针

在上面提到过,私有的成员变量在类内部是可以访问的。比如我们对不同的类进行加天数的操作后的结果是不同的:

int main()
{
	//类实例化
	Date d1;
	Date d2;
	//类初始化
	d1.InitDate();
	d2.InitDate(2023, 5, 14);
	//不同的日期类对象+100天
	d1.AddDate(100);
	d2.AddDate(100);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
那么成员函数是怎么知道是哪个对象调用的,并且获取到该类的成员变量并对其进行操作的?

这是由于,我们在调用成员函数时,其实是在替某个对象调用其成员函数。类对象的成员函数参数列表中其实有一个隐含的this指针,它在参数列表的左边
this指针就是调用成员函数的对象的指针,它的作用就是帮助成员函数调用成员变量。其实上面的AddDate函数本质上是这样的:

//Date& Date::AddDate(Date *const this, int day); //错误代码:this指针必须隐式传参

在函数内部是这样实现访问成员变量的:

{
	this->_day += day;
	while (this->_day > GetMonthDay(this->_year, this->_month))
	{
		this->_day -= GetMonthDay(this->_year, this->_month);
		++(this->_month);
		if (this->_month > 12)
		{
			++(this->_year);
			this->_month = 1;
		}
	}
	return *this;
}

虽然显式的用this指针访问成员变量是可以的,但是这样的代码很不好看,不简洁。

this指针的特性:

  1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值;
  2. 只能在成员函数的内部使用;
  3. this指针本质上是成员函数的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针;
  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。

总结

在这篇文章中,初步了解了类和对象,包括定义、实例化以及this指针。接下来会继续深入介绍类和对象的相关知识,希望大家持续关注哦

如果大家认为我对某一部分没有介绍清楚或者某一部分出了问题,欢迎大家在评论区提出

如果本文对你有帮助,希望一键三连哦

希望与大家共同进步哦

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

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

相关文章

NSSCTF之Misc篇刷题记录⑩

NSSCTF之Misc篇刷题记录⑩ [CISCN 2022 初赛]ez_usb[SWPUCTF 2021 新生赛]你喜欢osu吗&#xff1f;[SWPUCTF 2021 新生赛]Bill[SWPUCTF 2021 新生赛]二维码不止有二维码[HGAME 2022 week1]好康的流量[红明谷CTF 2022]MissingFile[广东省大学生攻防大赛 2021]这是道签到题[羊城杯…

TOGAF架构开发方法—阶段 F:迁移规划

本章介绍迁移规划;也就是说&#xff0c;如何通过最终确定一个 详细的实施和迁移计划。 一、目标 F阶段的目标是&#xff1a; 最终确定架构路线图以及支持实施和迁移计划确保实施和迁移计划与企业的管理和实施方法相协调 企业整体变更组合的变化确保关键利益相关者了解工作包和…

【什么是蜂窝移动网络】

从 DataReportal 2021 年 1 月的统计数据来看&#xff0c;全球 78 亿人口中&#xff0c;有 52 亿手机用户&#xff0c;46 亿互联网用户。能够接入网络的设备越来越多&#xff0c;体量越来越大&#xff0c;不知道你有没有好奇过&#xff0c;这样一个庞大的世界是如何被构造出来的…

【Linux】指令(下)

⭐博客主页&#xff1a;️CS semi主页 ⭐欢迎关注&#xff1a;点赞收藏留言 ⭐系列专栏&#xff1a;Linux ⭐代码仓库&#xff1a;Linux 家人们更新不易&#xff0c;你们的点赞和关注对我而言十分重要&#xff0c;友友们麻烦多多点赞&#xff0b;关注&#xff0c;你们的支持是我…

论文阅读:Multimodal Graph Transformer for Multimodal Question Answering

文章目录 论文链接摘要1 contribution3 Multimodal Graph Transformer3.1 Background on Transformers3.2 Framework overview 框架概述3.3 Multimodal graph construction多模态图的构建Text graphSemantic graphDense region graph Graph-involved quasi-attention 总结 论文…

【AIGC提示工程 - MidJourney教程:一】“Midjourney AI“是什么,为何众人皆谈?

关注元壤教育公众号系统学习AIGC提示工程课程。 更多AIGC好博客&#xff0c;请移步访问AIGC博客派 Midjourney AI是一个极富创造性的工具&#xff0c;它能够帮助用户通过指令创建图像。这些图像是基于用户的想象力而创造的。 在本文中&#xff0c;我们将详细了解Midjourney AI。…

软件测试面试面对史上最难求职季,会哪些测试技能更容易拿到offer?

在一线大厂&#xff0c;没有测试这个岗位&#xff0c;只有测开这个岗位。这几年&#xff0c;各互联网大厂技术高速更新迭代&#xff0c;软件测试行业也 如果你在中小型公司&#xff0c;普通的测试工程师20K差不多到极限了&#xff0c;薪资想再进一步提升很困难。而在阿里巴巴P…

【AIGC提示工程 - MidJourney教程:二】《MidJourney参数大全指南:实现最佳图像输出的关键》

关注元壤教育公众号系统学习AIGC提示工程课程。 更多AIGC好博客&#xff0c;请移步访问AIGC博客派 这篇文章介绍了不同的MidJourney参数和提示词&#xff0c;帮助你创建你选择的图像。探索如何使用不同的风格和参数进行操作。 如果你使用Midjourney应用&#xff0c;你就知道提示…

NetSuite SuiteQL 内建函数

之前写过一篇文章介绍SutieQL Query Tool&#xff0c;今天继续挖掘一下SuiteQL的价值。 NetSuite SuiteQL Query Tool_netsuite好用吗_毛岩喆的博客-CSDN博客这是一个非常好的NetSuite数据查询工具&#xff0c;免费、强大&#xff01;所以忍不住安利给大家。首先介绍一下背景&…

Redis系列--redis持久化

一、为什么需要持久化 redis本身运行时数据保存在内存中&#xff0c;如果不进行持久化&#xff0c;那么在redis出现非正常原因宕机或者关闭redis的进程或者关闭计算机后数据肯定被会操作系统从内存中清掉。当然&#xff0c;redis本身默认采用了一种持久化方式&#xff0c;即RD…

11.Kafka系列之Stream实践

Kafka Streams是一个基于Apache Kafka的处理库&#xff0c;可以用于实现高效、可扩展的实时数据处理应用程序。它是一个轻量级的库&#xff0c;允许你在Java和Scala中创建和运行流处理应用程序&#xff0c;这些应用程序可以读取输入流&#xff0c;执行各种数据转换&#xff0c;…

MyBatis的配置案例

Mybatis中Map的使用 如果需要所有的代码&#xff0c;可以看我上一篇 在接口中定义 int addUser1(Map<String,Object> map); 插入语句 <insert id"addUser1">insert into user(id,name,pwd) values (#{userid},#{username},#{userPwd})</insert> …

Vue3-黑马(十)

目录&#xff1a; &#xff08;1&#xff09;vue3-antdv-全局提示与校验 &#xff08;2&#xff09;vue3-进阶-router-入门 &#xff08;3&#xff09;vue3-进阶-router-动态导入-嵌套路由-重定向 &#xff08;1&#xff09;vue3-antdv-全局提示与校验 当用户新增修改&…

redis(11)

一)基于Set集合实现点赞功能: 在我们的博客表当中&#xff0c;每一篇博客信息都有一个like字段&#xff0c;表示点赞的数量 需求: 1)同一个用户只能点赞一次&#xff0c;再次进行点赞则会被取消&#xff1b; 2)如果当前用户已经点赞过了&#xff0c;那么点赞按钮高亮显示&…

传输层:UDP协议

传输层中有两个重要的协议&#xff1a;TCP协议和UDP协议。 本博文分享的是UDP协议&#xff0c;本文将从UDP的协议格式、UDP的特定以及其缓冲区入手。 传输层 传输层的作用是负责数据能够从发送端传输到接收端&#xff0c;主要是传输策略。 端口号 端口号标识的是一个主机上进…

【AIGC提示工程 - Midjourney教程:三】如何利用Midjourney AI创作一幅杰出的艺术作品?

关注元壤教育公众号系统学习AIGC提示工程课程。 更多AIGC好博客&#xff0c;请移步访问AIGC博客派 要在Discord上使用Midjourney机器人&#xff0c;您需要输入一个指令。指令能帮助您创建图片、修改默认设置、监控用户信息以及执行其他有用的操作。如果想要生成一张图片&#x…

RHCSA之Linux目录结构

目录 Linux目录结构 Linux目录结构的特点 分区‘加载’于目录结构 Windows与Linux目录结构区别 工作目录、用户家目录及路径 Linux的文件类型大致可分为 查看文件系统类型 方法一 ls -l 路径 方法二 file 路径 RHCSA之Linux目录结构 使用树形目录结构来组织和管理文件 整个…

51单片机(十三)DS18B20温度传感器

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

第14届蓝桥杯C++省赛(初级)真题

一、选择题&#xff08;50分&#xff09; 第 1 题 单选题&#xff08;10分&#xff09; C中&#xff0c;bool类型的变量占用字节数为 ( )。 *选择题严禁使用程序验证&#xff0c;选择题不答或答错都不扣分 A.1 B.2 C.3 D.4 第 2 题 单选题&#xff08;10分&#xff09;…

Windows 下载与安装CUDA和Pytorch【安装教程、深度学习】

参考链接&#xff1a;Windows 下安装 CUDA 和 Pytorch 跑深度学习 - 动手学深度学习v2_哔哩哔哩_bilibili 0.准备工作 请确保你是NVIDIA的显卡&#xff08;不能是AMD、集成显卡&#xff09; 1.下载CUDA 打开developer.nvidia.com/cuda-downloads&#xff0c;打开有点慢 选择…