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

news2024/12/22 19:38:07

前言:

介绍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指针很重要,在后面会一直用,下一章将会介绍六大默认成员函数。

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

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

相关文章

网络七层模型之应用层:理解网络通信的架构(七)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

算法——模拟专题(一篇搞定)

在本专栏已经更新双指针算法,滑动窗口算法,二分查找算法,前缀和算法以及位运算算法,欢迎大家跳转至相关专题阅读 此篇文章为大家带来算法专栏的模拟专题 模拟算法本质就是比葫芦画瓢&#xff0c;思路比较简单&#xff0c;就是将演算流程转化为代码 目录 1.替换所有的问号 1.1…

eclipse导入svn项目

1、配置maven 2、用svn引入项目 3一直点击next,到最后选完成。

Orangedx:引领新一轮 BTCFi 浪潮

“OrangeDx 作为新一轮 BTCFi 浪潮引领者被市场寄予厚望 &#xff0c;前不久在 FinceptorApp 的平台的公开销售 20 万美元的额度仅在几秒售罄&#xff0c;而其即将以 Startup 方式登陆 Gate 平台也同样备受市场期待。” 自 Ordinals 面向市场为比特币生态带来全新的资产发行方案…

函数作用域和块级作用域:JavaScript中的变量作用域解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

OpenGL学习笔记【4】——创建窗口,给窗口添加渲染颜色

一、前三章节的前情回顾 章节一&#xff1a;上下文(Context) OpenGL学习笔记【1】——简介-CSDN博客 章节一讲述了OpenGL在渲染的时候需要一个Context来记录了OpenGL渲染需要的所有信息和状态&#xff0c;可以把上下文理解成一个大的结构体&#xff0c;它里面记录了当前绘制使…

【@changesets/cli】变更集实战教程

一、背景概述 前端目前基于Monorepo架构的npm包开发很普遍&#xff0c;在开发完毕后&#xff0c;我们需要对包进行版本号升级&#xff0c;并且部署&#xff0c;这些操作如果是手动来操作的话&#xff0c;很麻烦&#xff0c;而且容易出错。 例如有这样的场景&#xff1a; -ap…

【可用Claude Opus模型】Claude3国内镜像站,亲测完全超越GPT-4(可用Claude Opus,官网价值20刀)

#今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用Claude 3吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像站到处都是…

C++ 扫描当前路径下文件并删除大文件

C 扫描当前路径下文件并删除大文件 C获取当前路径扫描文件路径下规定后缀名称的文件计算文件大小 1. 获取当前路径 使用<Windows.h>中的GetCurrentDirectory方法实现&#xff0c;单独编写验证程序如下&#xff1a; #include<iostream> #include<Windows.h&g…

YOLOv9改进策略:IoU优化 | Powerful-IoU更好、更快的收敛IoU,效果秒杀CIoU、GIoU等 | 2024年最新IoU

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文独家改进&#xff1a;Powerful-IoU更好、更快的收敛IoU&#xff0c;是一种结合了目标尺寸自适应惩罚因子和基于锚框质量的梯度调节函数的损失函数 &#x1f4a1;&#x1f4a1;&#x1f4a1;MS COCO和PASCAL VOC数据集实现涨点 YO…

R语言基础入门

1.保存或加载工作空间 改变工作目录——进行文件读写&#xff0c;默认去指定文件进行操作。&#xff08;使用R时&#xff0c;最好先设定工作目录&#xff08;setwd(),getwd()&#xff09;&#xff09; setwd(“工作文件路径”)&#xff1a;建立工作目录 getwd&#xff08;&…

【Mysql数据库基础07】DDL 数据定义语言

Data Definition Language 1 库的操作1.1 create 创建1.2 alter 修改1.3 drop 删除 2 表的操作2.1 表的创建2.2 表的修改2.2.1 修改表名2.2.2 修改列名2.2.3 修改列的类型和约束2.2.4 添加列2.2.5 删除列 2.3 表的删除2.4 表的复制 3 练习 1 库的操作 1.1 create 创建 create…

jvm(虚拟机)运行时数据区域介绍

Java虚拟机&#xff08;JVM&#xff09;运行时数据区域是Java程序在运行过程中使用的内存区域&#xff0c;它主要包括以下几个部分&#xff1a; 程序计数器&#xff08;Program Counter Register&#xff09;&#xff1a; 程序计数器是一块较小的内存区域&#xff0c;是线程私有…

法律合规| AI产品法律风险应对措施全解析

在此前推文中我们全面分析了生成式人工智能算法模型可能遇到的法律风险&#xff0c;那么这些风险应该如何应对呢&#xff1f; 1、隐私泄漏风险&#xff1a;企业需要遵守数据安全法和个人信息保护法的规定&#xff0c;确保数据来源合法&#xff0c;使用时获得用户授权&…

citus的快速开始

准备 dockercitus最新版本&#xff08;docker pull citusdata/citus&#xff09; docker网络 docker network create --subnet172.72.9.0/24 citus-test docker network ls启动citus服务 启动协调节点 docker run -dit --name citus-cod -p 5433:5432 -e POSTGRES_PASSWOR…

【vue3学习之路(一)】

文章目录 前言一、vue3项目创建1.1环境准备1.1.1 基于 vue-cli 创建&#xff08;脚手架创建&#xff09;1.1.2 基于 vite 创建&#xff08;推荐&#xff09; 二、熟悉流程总结 前言 参考视频&#xff1a;https://www.bilibili.com/video/BV1Za4y1r7KE?p10&spm_id_frompag…

使用uniapp 的 plus.sqlite 操作本地数据库报错:::table xxx has no column named xxxx

背景&#xff1a; 1、使用uniapp 的 plus.sqlite 进行APP本地数据库操作 2、SQLite 模块用于操作本地数据库文件&#xff0c;可实现数据库文件的创建&#xff0c;执行SQL语句等功能。 遇到&#xff1a;在之前创建的表上进行新增字段的操作时候&#xff0c;出现问题&#xff1a…

MyEclipse打开文件跳转到notepad打开问题

问题描述 windows系统打开README.md文件&#xff0c;每次都需要右键选择notepad打开&#xff0c;感觉很麻烦&#xff0c;然后就把README.md文件打开方式默认选择了notepad&#xff0c;这样每次双击就能打开&#xff0c;感觉很方便。 然后某天使用MyEclipse时&#xff0c;双击RE…

java第一次作业(二)

先写思路&#xff0c;再写代码&#xff0c;思路清晰&#xff0c;才能写对代码 7-6 求12...n的和 思路&#xff1a; 运用expression的字符串输出 重点&#xff1a; expression输出 代码&#xff1a; import java.util.Scanner; public class Main {public static void main…

数据运营常用的8大模型

✅作者简介&#xff1a;《数据运营&#xff1a;数据分析模型撬动新零售实战》作者、《数据实践之美》作者、数据科技公司创始人、多次参加国家级大数据行业标准研讨及制定、高端企培合作讲师。 &#x1f338;公众号&#xff1a;风姑娘的数字视角&#xff0c;免费分享数据应用相…