C++ -2- 类和对象(上)| 什么是类

news2024/9/28 23:28:22


文章目录

  • 1.面向过程与面向对象
  • 2.类的引入
  • 3.类的定义
    • 两种定义方式
  • 4.类的访问限定符
  • 5.类的作用域
  • 6.类的示例化
  • 7.类的对象大小计算
  • 8.类成员函数的this指针
    • C语言和C++的对比(this指针)
    • 空指针的问题
  • C语言和C++实现Stack对比

1.面向过程与面向对象

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

2.类的引入

  • C:struct 结构体,定义成员变量
  • C++:struct 定义成员变量和函数

C++ 把 结构体“升级成了” structclass

//C:
struct ListNode
{
	int* _a;
	int _size;
	int _capacity;
};


//CPP:
struct ListNode2
{
	void Init(size_t capacity)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		if (!_a)
		{
			perror("malloc fail");
			return;
		}
		_capacity = capacity;
		_size = 0;
	}

	//……

	int* _a;
	int _size;
	int _capacity;
};

3.类的定义

class classname
{    
    类体:由“类的成员”组成
    ……
}
  • 类的成员:
    • 变量 → 类的属性/成员变量
    • 函数 → 类的方法/成员函数

两种定义方式

  1. 声明和定义全在类体中 → 日常练习(注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。)

内敛函数的声明和定义不能分离,所以声明的时候就要直接定义。
代码量小、比较简单的函数一般直接在类中定义。

//CPP:
struct ListNode2
{
	void Init(size_t capacity)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		if (!_a)
		{
			perror("malloc fail");
			return;
		}
		_capacity = capacity;
		_size = 0;
	}

	//……

	int* _a;
	int _size;
	int _capacity;
};
  1. 声明放在.h头文件,定义放在.cpp文件 → 正式工作
//.h
class fantasy
{
	void Init(int capacity = 4);

	//……

	int* _a;
	int _size;
	int _capacity;
};

//.cpp
#include "test.h"
void fantasy::Init(int capacity)//意思是“Init”这个函数是“fantasy”这个类里的成员函数
{
	_a = (int*)malloc(sizeof(int) * capacity);
	if (!_a)
	{
		perror("malloc fail");
		return;
	}
	_capacity = capacity;
	_size = 0;
}
  • 成员变量命名规则的建议:
class DateRB
{
public:
	void Init(int year = 0, int month = 0, int day = 0)
	{
		year = year;
		month = month;
		day = day;
		//这样就很奇怪,到底是谁赋值给谁
	}
private:
	int year;
	int month;
	int day;
};

所以,我们建议区别命名:

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

4.类的访问限定符

  1. 公有(public)→ struct 默认
  2. 保护(protected)
  3. 私有(private)→ class 默认

一般:

class MyClass
{
public:
	成员函数;

private:
	成员变量;
};
  • 封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

5.类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。

class fantasy//新的作用域
{
	void Init(int capacity = 4);
	//……
	int* _a;
	int _size;
	int _capacity;
};

void fantasy::Init(int capacity)//指明成员属于哪个类域。
{
	_a = (int*)malloc(sizeof(int) * capacity);
	if (!_a)
	{
		perror("malloc fail");
		return;
	}
	_capacity = capacity;
	_size = 0;
}

6.类的示例化

类 → 相当于设计图
类的实例化 → 相当于根据设计图建房

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

int main()
{
	DateRB d1;//类的实例化 → 对象
	d1.Init();

	return 0;
}

7.类的对象大小计算

class DateRB
{
public:
	void Init(int year = 0, int month = 0, int day = 0)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;//4→ 0,1,2,3
	int _month;//4→ 4,5,6,7
	int _day;//4→ 8,9,10,11
	//内存:12byte
};

int main()
{
	DateRB d1;//类的实例化
	d1.Init();

	cout << sizeof(d1) << endl;//output:12

	return 0;
}

如上这个例子,sizeof(d1) = 12(byte)

  • 为什么成员变量在对象(d1)里,成员函数不在对象里?
    • 每个对象的成员变量不一样,需要单独存储
    • 调用的成员函数都是一样的,在公共区域 (代码段)

特别的:

// 类中仅有成员函数
class A2 {
public:
   void f2() {}
};
// 类中什么都没有---空类
class A3
{};

sizeof(A2) : ?
sizeof(A3) : ?

cout << sizeof(A2) << endl;//output:1
cout << sizeof(A3) << endl;//output:1

1 字节 不存储有效数据,只是占位,用来标识 对象被实例化出来。


8.类成员函数的this指针

在这里插入图片描述

C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。这个过程编译器自动完成。

void Init(int year = 0, int month = 0, int day = 0)
{
	_year = year;
	_month = month;
	_day = day;
}

//实际上:
void Init(DateRB* this, int year = 0, int month = 0, int day = 0)
{
	this->_year = year;
	this->_month = month;
	this->_day = day;
}

C语言和C++的对比(this指针)

在这里插入图片描述
在这里插入图片描述
对象 d1 调用函数时,this = &d1 这个地址会传给函数

  • this 指针 → 隐含的形参,储存在

空指针的问题

定义:DateRB* ptr = nullptr;

class DateRB
{
public:
	void Init(int year = 0, int month = 0, int day = 0)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void func()
	{

	}
private:
	int _year;
	int _month;
	int _day;
};


int main()
{
	DateRB* ptr = nullptr;
	ptr->func();//正常运行
	ptr->Init(2023, 2, 27);//运行崩溃
	(*ptr).func();//正常运行
	return 0;
}
  1. ptr->func();//正常运行
    在这里插入图片描述
  • 为什么会正常运行?
    • 此过程中,调用 func 函数,只是把 ptr 的内容(nullptr)传给了 this 指针,而函数运行过程中 没有对 this 指针解引用操作
  1. ptr->Init(2023, 2, 27);//运行崩溃
void Init(int year = 0, int month = 0, int day = 0)
{
	this->_year = year;
	this->_month = month;
	this->_day = day;
}

显然,Init 函数会对 this 指针 解引用操作对空指针解引用造成运行崩溃

  1. (*ptr).func();//正常运行
    ptr->func();一样,没有对this 指针解引用
  • sum.看到 '*' 或者 '->' 不一定进行了解引用操作

注意:不能这样调用函数👇

func();
DateRB::func();

C语言和C++实现Stack对比

  • CPP:

    1. 数据和方法都封装到类里面
    2. 控制访问方式(共有、私有)
  • C:

    1. 数据和方法分离
    2. 数据的访问控制是自由的,不受限制的
      • 譬如:取栈顶的元素,可以不通过调用函数的方式而直接访问👇

      • cpp Stack st; int top = st.a[st.top] 但是这需要了解栈的底层结构,并且容易出错


END

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

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

相关文章

java获取请求ip的方法

在上篇文章中我们介绍了 java获取请求 ip的方法&#xff0c;那么这篇文章我们就来详细讲解下获取请求 ip的方法。获取请求 ip的方法是基于 HTTP协议的&#xff0c;其原理如下&#xff1a; 1、用 web应用程序&#xff0c;将 web服务器端与客户端通过 HTTP协议通信。 2、客户端发…

LNMP架构和论坛搭建以及一键部署

数据流向 一、Nginx服务安装 1、关闭防火墙 [rootking ~]# systemctl stop firewalld [rootking ~]# systemctl disable firewalld [rootking ~]# setenforce 0 2、将所需软件包拖入/opt目录下 3、安装依赖包 yum -y install pcre-devel zlib-devel gcc gcc-c make 4、创建运…

Feign快速入门

文章目录 一、Feign1.1 Feign介绍1.2 Feign的使用步骤1.3 Feign的自定义配置1.3.1 配置方法 1.4 Feign的优化 一、Feign 1.1 Feign介绍 Feign是一个Java HTTP客户端&#xff0c;它使开发人员可以轻松地与RESTful API进行交互。Feign使用注释来描述REST API&#xff0c;它还支持…

Springboot整合Junit5

1 SpringBoot整合Junit &#xff08;一&#xff09;junit5 介绍 Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库 作为最新版本的JUnit框架&#xff0c;JUnit5与之前版本的Junit框架有很大的不同。由三个不同子项目的几个不同模块组成。 JUnit 5 JUnit Platfo…

音视频开发十九:SDL线程和事件

SDL事件相关API DL_Event 是SDL库中使用的一个数据结构&#xff0c;用于表示系统中发生的事件。一个事件可以是键盘按键、鼠标移动、游戏手柄移动、窗口事件等。SDL_Event 结构包含有关事件类型、事件发生时间和事件参数的详细信息。 SDL_Event 结构具有以下成员&#xff1a;…

[5 种有效方法] 适用于 Android 的通用解锁图案/密码

在当今世界&#xff0c;保护您的密码对于您的文件和数据的安全至关重要&#xff0c;尤其是在第三方应用程序盛行的情况下。为这些应用程序注册帐户不是问题&#xff0c;就像记住它们一样。但是&#xff0c;如果您不知何故忘记了手机密码&#xff0c;您仍然可以在不丢失宝贵数据…

突破规模化运维瓶颈 SREWorks云原生数智运维平台揭秘

作者&#xff1a; 钟炯恩——阿里云大数据基础工程技术团队运维专家 引言 突破规模化运维瓶颈是诸多IT规模增长的企业及组织当前遇到的比较棘手的问题。面对这些问题&#xff0c;多数人的第一反应是上云。但是上云之后我们会发现&#xff0c;即使云上的架构规模增大&#xf…

如何使用DNS实现融合CDN功能

将托管DNS解决方案与CDN配对可为您的网站提供额外的性能、可靠性和灵活性。 域名系统&#xff08;DNS&#xff09;是一种用于计算机、服务或连接到Internet或专用网络的任何资源的分层分布式命名系统&#xff0c;它将各种信息与分配给每个参与实体的域名相关联&#xff0c;它基…

ChatGPT 火了,一大批开源平替也来了

ChatGPT 凭一己之力让全球为 AI 沸腾&#xff0c;引发了科技巨头之间的聊天机器人军备竞赛。 众所周知&#xff0c;ChatGPT 的背后技术是 GPT(Generative Pre-trained Transformer)模型。GPT 是一种基于 Transformer 模型的自然语言处理模型&#xff0c;由 OpenAI 公司开发。它…

【elasticsearch部署】

安装elasticsearch 1.部署单点es1.1.创建网络1.2.加载镜像1.3.运行 2.部署kibana2.1.部署2.2.DevTools 3.安装IK分词器3.1.在线安装ik插件&#xff08;较慢&#xff09;3.2.离线安装ik插件&#xff08;推荐&#xff09;1&#xff09;查看数据卷目录2&#xff09;解压缩分词器安…

前端必备的nginx知识点

nginx学习&#xff0c;看这一篇就够了&#xff1a;下载、安装。使用&#xff1a;正向代理、反向代理、负载均衡。常用命令和配置文件,很全_java冯坚持的博客-CSDN博客 前端必备的nginx知识点 - 掘金 前言&#xff1a; 最近在做一个后台项目 ngixn简介 nginx是一款轻量级&…

【Sql】sql语句练习随记

本文通过最经典的“学生-成绩-课程-教师”表来帮助练习sql语句。 STUDENT表 SNO 学号SNAME 姓名SSEX 性别SBIRTHDAY 生日CLASS 班级 SCORE表 SNO 学号CNO 课程编号DEGREE 分数 COURSE表 CNO 课程编号CNAME 课程名称TNO 教师编号 TEACHER表 TNO 教师编号TNAME 教师姓名TS…

(包教包会)最强分布式锁工具:Redisson

今天来聊聊分布式锁的最强实现&#xff1a;Redisson 从分布式锁到Redisson实现非常详细&#xff0c;适合慢慢咀嚼~ 一. Redisson概述 1.1 什么是Redisson&#xff1f; Redisson是一个在Redis的基础上实现的Java驻内存数据网格&#xff08;In-Memory Data Grid&#xff09;。…

CRMEB开源商城/标准版后台默认admin路径修改、后台目录地址修改

默认admin路径修改 v4.7 版本开始兼容可以修改admin路径&#xff0c;可以根据自己的要求更换后台访问地址&#xff1b; 默认路径不能携带特殊字符、全部都为小写字母 修改后台admin默认路径 标准版本文件位置根目录/config/app.php 开源版本文件位置根目录/crmeb/config/app.p…

新增套餐/redis/QuartZ

套餐其实就是检查组的集合&#xff0c;例如有一个套餐为“入职体检套餐”&#xff0c;这个体检套餐可以包括多个检查组&#xff1a;一般检查、血常规、尿常规、肝功三项等。所以在添加套餐时需要选择这个套餐包括的检查组。 套餐对应的实体类为Setmeal&#xff0c;对应的数据表…

深度学习(7)之图像抠图 Image Matting算法调研

目录 1.Trimap和Strokes 2. 相关数据集 3.论文算法调研 3.1 Deep Image Matting 3.2 Semantic Image Matting 3.3 Background Matting 3.4 Background Matting V2 3.5 Semantic Human Matting 3.6 HAttMatting 3.7 MMNet&#xff1a;Towards Real-Time Automatic Portrait Matt…

Nginx虚拟主机、优化和防盗链

一、Nginx虚拟主机 1、基于域名的nginx虚拟主机的操作步骤 1.1 为虚拟主机提供域名和IP的映射(也可以使用DNS正向解析) echo "192.168.2.66 www.xkq.com www.wy.com" >> /etc/hosts1.2 为虚拟主机准备网页文档 mkdir -p /var/www/html/ly/ mkdir -p /var/w…

经典文献阅读之--VGICP(体素化的ICP匹配)

0. 简介 之前我们在以前的文章中介绍了很多有关于点云匹配相关的知识&#xff0c;最近两年处理GICP这一大一统的ICP匹配方法以外&#xff0c;还有一个工作对体素化和ICP这两者打起了心思&#xff0c;《Voxelized GICP for Fast and Accurate 3D Point Cloud Registration》提出…

动车的颜色种类

01 大家平时见到最多的动车 可能就是白色的吧 和谐号动车组开行后 白就是动车的经典配色 白色为底 车腰一条蓝色飘带让其设计感十足 我们也可以把这种动车配色 称为和谐白 02 复兴号CR400AF型电力动车组 最高运营速度350公里每小时 因其车身采用银色底色 搭配侧窗…

大数据时代必备技能,从0开始学好数据可视化

当今社会&#xff0c;数据可视化已经成为了一项非常重要的技能。随着大数据时代的到来&#xff0c;越来越多的人开始关注数据可视化&#xff0c;并希望能够快速地掌握这项技能。那么&#xff0c;如何快速学习数据可视化呢&#xff1f;以下是AdBright数据分析师的一些建议。 什么…