C++关于类和对象的基础语法

前言:

介绍c++中类和对象的基础语法和注意事项,这里是c++入门的第一道坎,细节很多,在后面的更深的学习中还会反复提到。

目录

前言:

1.OO语言

2.类的定义

3.类的访问限定符与封装的引入

4.类的实例化

5.关键字this指针(很重要)

6.this空指针问题

总结:

类的访问限定符与this指针很重要,在后面会一直用,下一章将会介绍六大默认成员函数。


1.OO语言

谈到类,就离不开对象,而像我们的c++,Java也就是面对对象(Object Oriented)的语言,什么是面对对象呢?

简单来说,就是让一件事分为不同的对象,靠对象间的交互完成,但我们c++并不是完全的面对对象,因为是兼容c语言的,而c语言就是经典的面向过程的语言。

2.类的定义

c++中把结构体升级成了类(其实结构体也是类的一种),类里面可以定义函数。

	 class className
	{
	//类体,由成员函数和成员变量组成
	};                        //结尾带分号
  • class为定义类的关键字,className为类的名字,类中的变量称为类的属性或是成员变量

  •  函数称为类的方法或是成员函数,以类定义的变量可以叫做对象

注意

  1. 成员变量和函数定义的位置不会影响,类会在调用的时候在类体里面整体搜索。  
  2. 如果是用struct定义一个类(class有些不同,下面再提),成员函数可以直接定义在类里面,也可成员函数声明和定义分离,也就是如果定义在另一个文件里面,定义时就要标明函数的来源,例如类名:函数名,声明放在头文件中时,注意缺省参数要在声明里缺省。

3.类的访问限定符与封装的引入

  • public修饰的成员在类外是可以直接被访问的
  • protected和private修饰的成员在类外不能直接访问
  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现为止
  • 如果没有访问限定符,作用域就到类的结束
  • class的默认访问权限为private,struct为public(主要因为struct要兼容c)

注意

  1. 不建议使用默认的访问权限,大部分情况下成员变量不希望被改变,要用private或者protected定义(目前二者没有区别,在继承的部分会介绍区别),所以一般建议成员函数被共用就用public定义,不是就用private。
  2. c++中struct还可以继续当做结构体使用,class也可以但是不会使用class当做结构体。
  3. 成员变量定义时最好前面加上_,可以在前面或者在后面,防止成员变量与成员函数形参名相同导致出错。
  4. 类定义了一个新的作用域,再类体外定义成员时,需要用::作用域操作符指明成员属于哪个类域、

封装:了解了基本的类的语法,我们再来简单的谈封装,封装就是通过类将数据及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部的实现细节,控制某些方法可以在类外部直接被使用。

4.类的实例化

与结构体一样。类在创建的时候没有开空间,而创建类 类型的变量的时候(也就是对象)时开了空间,此时就能通过对象去访问类里面的成员了,这就叫做类对象的实例化,所以创建的类的成员的成员变量只是声明,并没有开辟空间。

然后,我们需要知道一个重要的点,假设我们现在定义一个这样的类:

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};



int main()
{
	Date d1;
	Date d2;
 
    //一个类创建出了两个对象,但是为分别存储的(这样写是不对的,只是举例说明)
    d1._year++;
    d2._year++;
  
    //一个类创建出了两个对象,分别调用的成员函数是同一个,存放在代码段
	d1.Init(2023, 3, 22);
	d2.Init(2024, 3, 22);


	return 0;
}

d1和d2分别访问的成员变量是同一个吗?d1和d2分别访问的成员函数是同一个吗?

我们需要知道,成员变量在对象中,成员函数不在对象中,怎么理解呢?

因为每一个对象都有独立的空间,每个对象的成员变量都是独立存储的,所以两个对象访问一样的成员变量但其实不是同一个;而类里的函数是公有的,成员函数直接放到对象里面就浪费空间了,所以大小也不计算在类里,而是放到一个公共的区域(代码段),所以调用类里面的函数就去代码段里去找(汇编中call这个函数的地址,call这条指令就存放在代码段里面)

注意:没有成员变量的类的大小是多少?大小是1byte,这1byte不存储有效的数据,用来占位,标识对象被实例化定义出来了,仅仅是标记对象存在过。

5.关键字this指针(很重要)

	d1.Init(2023, 3, 22);
	d2.Init(2024, 3, 22);

还是上面的代码,虽然d1,d2都是调用的同一个函数,但编译器是怎么确定函数中的_year是谁的呢?这就引入了this指针:

 实际传参时编译器自动传的还有调用对象的地址,然后函数中使用一个this指针接收,类型就是这个类,d1调用,this中就是d1的地址,d2调用,this中就是d2的地址。

注意

  1. 函数里面可以出现this,但是形参与实参不能自己加,一般里面也不加。
  2. this指针是存放在栈上的(因为它是隐形的形参,vs下是通过ecx寄存器存储),不要跟代码段混淆了,this指针是形参是数据,传参需要压栈;call函数的地址是指令,指令放在代码段。

6.this空指针问题

class Date
{
public:
	void Init(int year, int month, int day)
	{
		/*_year = year;
		_month = month;
		_day = day;*/

		cout << this << endl;
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}

	void func()
	{
		cout << this << endl;
		cout << "func()" << endl;
	}
private:
	int _year=0;
	int _month=0;
	int _day=0;
};



int main()
{
	Date* ptr = nullptr;
	ptr->func();//正常运行
	ptr->Init(2024, 3, 22);//运行崩溃
    (*ptr).func();//正常运行
    return 0;
}

 现在想调用func(),直接使用->去调用会出问题吗?

分析一下,func是成员函数,但并不在对象里面,所以调用这个函数就要去call它的地址,而这句指令存放在代码段中,这里的箭头就是去Date这个类域中找func,没有解引用的意思,而传过去的ptr的地址虽然是空(this地址也是空),由于func中没有对*this解引用,所以没问题。另外,如果我们去掉ptr->就访问不到这个成员函数了,其一是因为不用对象调用函数就去全局里找么人func又只是在类这个域中,肯定找不到,其二是因为去掉就没法出传递this指针(Date::func()没有传递给this指针的内容)

那第二个为什么会崩溃呢?

因为传过去的ptr的地址为空,所以this也是空,函数里面又有解引用所以运行就崩溃了。

那第三个又是为什么正常运行呢?

这还是编译器的处理,编译器很聪明,调用类的成员函数会优先传this指针去看类里面有没有这个函数,而不是先解引用。

所以我们可以理解为在调用类的成员函数的时候使用->或者.,会优先去传this指针去类里面找(编译器的处理),而不是理解为c语言中的解引用,但如果传的是个空指针,而且这个成员函数内还对this指针解引用了,这时就会报错了。

总结:

类的访问限定符与this指针很重要,在后面会一直用,下一章将会介绍六大默认成员函数。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Magic Copy:一键AI抠图,在浏览器中获得任何图像素材

Magic Copy&#xff1a;轻松一点&#xff0c;精准抠图&#xff0c;让创意无限放大&#xff01; - 精选真开源&#xff0c;释放新价值。 概览 Magic Copy&#xff08;AI智能抠图插件&#xff09;是一个创新型的浏览器扩展工具&#xff0c;其独特之处在于能够无缝集成于用户的网…

项目配置之道:优化Scrapy参数提升爬虫效率

前言 在当今信息时代&#xff0c;数据是无处不在且无比重要的资源。为了获取有效数据&#xff0c;网络爬虫成为了一项至关重要的技术。Scrapy作为Python中最强大的网络爬虫框架之一&#xff0c;提供了丰富的功能和灵活的操作&#xff0c;让数据采集变得高效而简单。本文将以爬…

Kafka安装配置

#安装启动之前必须配置好zookeeper 可以参考zookeeper安装配置-CSDN博客 一、下载安装包&#xff0c;并解压 #创建目录 mkdir -p /kafka/{install,data} #进入/kafka/install目录下 cd /kafka/install #下载kafka wget https://archive.apache.org/dist/kafka/3.7.0/kafka_2…

JSONP 实现跨域请求案例

后端使用 express 搭建&#xff0c;案例代码如下&#xff1a; const express require(express)const app express() const PORT 3000app.get(/data, (req, res) > {const jsonData {name: Alan,age: 666,city: GD}const callback req.query.callback // 获取前端中的回…

【Linux】Linux开发工具-vim / 编译器-gcc/g++ / 调试器-gdb / git操作 / 项目自动化构建工具-make/Makefile

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;Linux_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.在Linux写自己的第一个程序 1.1 nano指令 1.2 nano指令的使用 1.2.1 介绍 1.2.2 演示 1.2.2.1 创建.c文件 1.2.2.2 nano cod…

值迭代和策略迭代【强化学习】

强化学习笔记 主要基于b站西湖大学赵世钰老师的【强化学习的数学原理】课程&#xff0c;个人觉得赵老师的课件深入浅出&#xff0c;很适合入门. 第一章 强化学习基本概念 第二章 贝尔曼方程 第三章 贝尔曼最优方程 第四章 值迭代和策略迭代 文章目录 强化学习笔记一、Value It…

基于Docker的JMeter分布式压测!

一个JMeter实例可能无法产生足够的负载来对你的应用程序进行压力测试。如本网站所示&#xff0c;一个JMeter实例将能够控制许多其他的远程JMeter实例&#xff0c;并对你的应用程序产生更大的负载。JMeter使用Java RMI[远程方法调用]来与分布式网络中的对象进行交互。JMeter主站…

【运放】LM358和LM324

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

一个python实现的Kline框架

起因是想研究量化交易&#xff0c;然后核查算法的落角点&#xff0c;比如哪些指标的组合可以入场做单&#xff0c;没有一个形象化的工具算法写起来总是感觉差强人意。 初步想法是需要一个数据串&#xff0c;里面记录一组开高低收量&#xff0c;然后打开程序后可以将这个基础数…

【基于skyent的热更思考】

基于skyent的热更思考 skynet-inject热更原理关键源码分析热更方式拓扑图注意事项 skynet-inject热更原理 inject是一个用于动态加载 Lua 代码文件并执行其中定义的函数的功能。可以在运行时动态加载 Lua 代码文件&#xff0c;然后调用其中定义的函数&#xff0c;通过修改模块…

【小米汽车SU7实测】 小米汽车su7到底行不行?小米新能源轿车体验感怎么样?

小米汽车SU7是小米汽车的首款车型&#xff0c;定位“C级高性能生态科技轿车”&#xff0c;也是小米迈入新能源赛道的首次成果落地。 首先&#xff0c;让我们来谈谈它的性能。试驾过程中&#xff0c;小米SU7展现出了惊人的加速能力&#xff0c;0-100km/h加速仅需2.78秒&#xf…

射频前端架构之Phase8简介

Phase8系列方案有三种&#xff0c;分别是Phase8、Phase8M、Phase8M。 Phase8与Phase8M方案采用的是低频及中高频两颗L-PAMiD构成完成方案&#xff0c;目标是高端及旗舰手机&#xff0c;方案强调强大的射频能力&#xff0c;以及完整的CA、EN-DC支持&#xff0c;当然这两个方案的…

C++读取文本文件中的汉字出现乱码的原因及解决措施

大家好&#xff01; 作者今天在写代码时遇到了读取文本文件中的汉字时出现乱码的情况&#xff0c;所以本文介绍Windows操作系统中&#xff0c;C读取文本文件中的汉字出现乱码情况原因及解决措施。 下面代码可以读取Stu.txt中的内容并输出&#xff1a; ifstream ifs; ifs.open(…

Python编程—Ajax数据爬取

Python编程—Ajax数据爬取 ​ 在浏览器中可以看到正常显示的页面数据&#xff0c;而使用requests得到的结果中并没有这些数据。这是因为requests获取的都是原始HTML文档&#xff0c;而浏览器中的页面是JavaScript处理数据后生成的结果&#xff0c;这些数据有多种来源&#xff…

模糊PID模糊化(三角隶属度函数SCL代码)

模糊PID系列文章大家可以查看PID专栏,这里我们再次对模糊化进行细分,为大家呈现不同的程序写法。 1、模糊控制模糊PID学习笔记 https://rxxw-control.blog.csdn.net/article/details/124380674https://rxxw-control.blog.csdn.net/article/details/1243806742、模糊PID(三角…

25.8 MySQL 数据处理之增删改

1. 数据完整性问题 数据完整性问题: 数据的插入, 更新, 删除等操作都需要满足数据库表的完整性约束条件, 否则这些操作将会失败. 完整性约束在数据库设计中起到了至关重要的作用, 它们确保了数据库中数据的准确性和一致性.约束条件的全称通常被称为完整性约束条件(Integrity Co…

物理查询优化(二):两表连接算法(附具体案例及代码分析)

前言 关系代数的一项重要操作是连接运算&#xff0c;多个表连接是建立在两表之间连接的基础上的。研究两表连接的方式&#xff0c;对连接效率的提高有着直接的影响。 连接方式是一个什么样的概念&#xff0c;或者说我们为何要有而且有好几种&#xff0c;对于不太了解数据库的人…

Sentry(Android)源码解析

本文字数&#xff1a;16030字 预计阅读时间&#xff1a;40分钟 01 前言 Sentry是一个日志记录、错误上报、性能监控的开源框架&#xff0c;支持众多平台&#xff1a; 其使用方式在本文不进行说明了&#xff0c;大家可参照官方文档&#xff1a;https://docs.sentry.io/platforms…

2000-2022年上市公司客户、供应商集中度数据

2000-2022年上市公司客户、供应商集中度数据 1、时间&#xff1a;2000-2022年 2、来源&#xff1a;上市公司年报 3、指标&#xff1a;年份、股票代码、股票简称、行业代码、省份、城市、省份代码、城市代码、上市状态、前五名客户产生的营业收入_亿元、占全年营业收入的比例…

告别写作瓶颈,AI写作软件为你开启新篇章

如今&#xff0c;文字的力量对于人们愈发凸显。然而&#xff0c;对许多人来说&#xff0c;写作却是一项困难而耗时的任务。从学生的论文到商务报告&#xff0c;从小说创作到文案&#xff0c;写作瓶颈常常成为人们面临的挑战。然而&#xff0c;随着人工智能技术的不断发展&#…