【C++进阶之路】类和对象(上)

news2024/12/25 9:16:29

文章目录

  • 一.面向对象和面向过程
  • 二.类的引入——结构体
  • 三.类的定义
    • 1.类定义的两种方式
      • 在类里面定义函数
      • 在类外定义函数——类域
    • 2.访问限定符
    • 3.封装——面向对象的三大特性
    • 4.类的实例化
  • 四.类对象模型
    • 求一个类的大小
  • 五.this指针
    • 基本认识
    • 代码解读

一.面向对象和面向过程

  • 面向对象:是软件开发方法中的一种。是一种对现实世界理解和抽象的方法;是思考问题相对高级的方法。在面向对象时,我们会建立对象,主要在意对象的行为。
  • 面向过程:分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。是一种思考问题的基础方法。

  • 我们以做一道红烧肉的实现来体现过程和对象的区别
  • 面向过程: 1.去买肉,切肉 2.起锅,烧油,调糖色,3.放入锅中,加入调料调味,4.顿好出锅
  • 面向对象:1.买好红烧肉 2.把红烧肉放在锅中,3.将红烧肉盛出
  • 因此:面向对象开发更加方便高效,面向过程较为繁琐。

面向对象的过程更加注重对象从而更加高效,但功能的实现有时候还是需要我们自己实现。

二.类的引入——结构体

  • 类定义:类 +类名+{ };
  • 在C++中,结构体被升级成了类,但C语言的用法还是可以使用的.

  • 证明:
struct student
{
	char _name[6];
	int _age;
	int _number;
	student* _p;
};
  • 这里的结构体被升级成了类,在C++里类名是可以被用作定义变量的,但C语言中不行,当然如果你想在这里用C语言的语法也是可以的。
  • 说明:变量的定义为了与函数调用变量进行区分,我们一般都在变量的前面加上 _

  • 类里面是可以定义函数的
struct student
{
	void Print()
	{
		cout << "Print" << endl;
	}
	char name[6];
	int age;
	int number;
	student* p;
};

  • 类被当做一个域叫做——类域
  • 目前我们学过的C++的域——全局域,局部域,命名空间域,类域。

三.类的定义

  • 与结构体相似:class +类名 +{} ;
  • 注意:;——分号不可省

1.类定义的两种方式

在类里面定义函数

class student
{
	void Print()
	{
		cout << "Print" << endl;
	}
	char _name[6];
	int _age;
	int _number;
	student* _p;
};

在类外定义函数——类域

void student::Print()
{
	cout << "Print" << endl;
}
class student
{
	void Print();
	char _name[6];
	int _age;
	int _number;
	student* _p;
};
  • 注意:在类外定义函数,需要在类里面声明一下这个函数,并且要在定义的时候函数名前加上类名+作用域限定符,表明这是该类的函数。

2.访问限定符

  • public :公有——类外可以直接访问
  • private:私有——类外不可以直接访问
  • protecter:与private类似——类外不可以直接被访问(在继承中会用到)

  • 注意
  • 1.C++为了兼容C语法,默认结构体类的成员为公有。但在class中,默认成员为私有,不能从类外直接进行访问
  • 2.其作用范围从其出现开始到遇到下一个访问限定符/类作用域结束为止。
  • 3 访问限定符只在编译期间有用,是对语法的检查,因此只在编译期间报错,在数据已经被加载到内存中时,这时看访问限定符其实是一样的,访问限定符更像是一个门槛,一个前提。

3.封装——面向对象的三大特性

  • 封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
  • 说明:隐藏对象的属性和实现细节——是通过private进行实现的。外部接口——实现的函数。
  • 封装是为了更好的管理和保护数据,避免对数据进行破坏。因为会调用接口进行管理数据,这里的接口就是我们设置的规则。并且接口一般都是公开的

4.类的实例化

  • 定义一个类就如同定义了一个结构体,跟结构体的自定义类型相似,我们定义类时只是说明了类里面有什么内容,并不能直接使用类的内容,那与定义一个结构体变量就如同类的实例化
  • 这也间接反映出了域里面并不一定都是变量的定义,也有可能都是变量的声明。
class student
{
public:
	void Print();
private:
	char name[6];
	int age;
	int number;
	student* p;
};
int main()
{
	student A;//这样我们就完成了类的实例化。
	return 0;
}

四.类对象模型

求一个类的大小

  • 与求结构体的大小相似:

1.第一个成员在与结构体变量偏移量为0的地址处。

2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

说明: 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

  • 需要我们注意的是在C语言中结构体中至少定义一个变量,而在C++中结构体被升级为类,可以为空,甚至可以在里面定义函数。
  • 那函数占不占内存呢?

实验便知:

class student1
{
public:
	void Print()
	{
		cout << "Print" << endl;
	}
private:
	int age;
};
class student2
{
public:
	void Print()
	{
		cout << "Print" << endl;
	}
};
class student3
{

};
int main()
{
	cout << sizeof(student1) << endl;
	cout << sizeof(student2) << endl;
	cout << sizeof(student3) << endl;
	return 0;
}

在这里插入图片描述

  • 通过student2与student3进行对比可说明——函数是不占用类里的空间。
  • 函数占用的空间在哪呢?——公共代码段(当执行时,调用此函数的代码执行即可)
  • 说明:不同的对象调用的函数是一样的。

在这里插入图片描述
在这里插入图片描述
说明:这样设计是为了空间的节省,不同对象调用的函数是一样的,在调用时执行函数的代码即可,这样一码多用节省了空间。

  • 通过student1与studen2进行对比可简单的说明——对齐方式与结构体的对齐方式一致。
  • student3的大小为1——说明类的大小最小为1,至于为什么不能为0,假设如果为0,则开辟空间为0,通过以前的学习可知,一个变量的开辟是必须有地址的,0空间无地址,互相矛盾,因此不能为0,这里的1充当的是占位符的作用。

五.this指针

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

基本认识

class Date
{
public:
	void Print()//括号里面相当于(this),这里的this也是不能写出来的,也是隐式转换
	{
		cout << _year <<"-"<< _month<<"-" <<_year<< endl;
		//在函数里面可以使用this指针,上面的代码写完整就是
		cout <<this-> _year <<"-"<<this-> _month<<"-" <<this->_year<< endl;
		//this=NULL 这也是不行的,因为this指针是一个const修饰的类型,不能进行修改。
		//说明定义一个变量int * const this,const具有就近原则
		//放在this前this本身不能修改
		//放在*前说明*this不能被修改
	}
	void Init(int year = 1 ,int month =1,int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _day;
	int _month;
	int _year;
};

int main()
{
	Date A;
	A.Init();
	//A.Init(this);这样写是不对的,因为this是隐式转换的,这里的this转换为A的地址;
	//A.Init(&A);其实就转换为了指定对象的地址,怎么进行转换呢?A.这里通过A就能找到A的地址。
	A.Print();
	return 0;
}
  • 我们看这里的函数调用,为什么不用通过传类变量的地址,直接就能使用类里面的变量?
  • 说明:这里隐含了一个this指针,那this指针是什么呢?
  • 其实这里的this指针就是类实例化的地址。
  • 总结:this指针不能显示传参, 函数定义的参数处也不能显示出来函数内部可以使用访问对象的变量,但对this指针不能进行修改

代码解读

struct A
{
public:
	void PrintA()
	{
		cout << _a << endl;
		//这里_a相当于this->_a发生了对空指针解引用的情况
	}


	int _a;
};

int main()
{
	
    A* p = NULL;
	p->PrintA();
	//说明这里p->PrintA()等于(*p).PrintA()
	//但这里并没有语法错误:因为这里是调用里面函数,函数并不占用类的空间,因此可以调用类的函数
	//但是这里将p传进去了,p是一个空指针,在里面访问变量时,会产生对空指针解引用的情况,因此
	//具体的报错位置在函数里面的变量使用
}
  • 代码是否报错?具体报错在哪?
  • 报错,报错位置在函数里面。
struct A
{
public:

	void Show()
	{
		cout << "Show()" << endl;
	}

	int _a;
};

int main()
{
	
    A* p = NULL;

	p->Show();
}
  • 代码是否报错?具体报错在哪?

  • 不会报错,因为函数里面没有对变量的访问。

  • 总结:this指针可以为空,但必须通过对象进行调用函数。

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

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

相关文章

【移动端网页布局】流式布局案例 ③ ( 实现搜索栏功能 | 伪元素选择器 | 子绝父相 | 外边距塌陷处理 | 二倍精灵图处理方案 )

文章目录 一、搜索栏样式及核心要点1、实现效果2、自动伸缩搜索栏实现3、搜索栏父容器设置4、搜索栏左右两侧的按钮盒子5、搜索栏盒子6、二倍精灵图处理方案 二、完整代码示例1、HTML 标签结构2、CSS 样式3、展示效果 一、搜索栏样式及核心要点 1、实现效果 上一篇博客中 , 完成…

2022年职业教育技能大赛网络安全 linux系统渗透提权

B-10&#xff1a;Linux 系统渗透提权 任务环境说明&#xff1a; ✓ 服务器场景&#xff1a;Server2202&#xff08;关闭链接&#xff09; ✓ 用户名&#xff1a;hacker 密码&#xff1a;123456 使用渗透机对服务器信息收集&#xff0c;并将服务器中 SSH 服务端口号作为 flag…

API 接口自动化测试的基本原理及实战教程

目录 常用API接口协议介绍 Http协议接口请求的介绍 HTTPS协议 SMTP协议 SNMP协议 FTP协议 API 接口自动化测试的基本原理 常用API接口协议介绍 HTTP协议 超文本传输协议 它是用来在Internet上传送超文本的传送协议&#xff0c;运行在TCP/IP协议族之上&#xff0c;它可…

Docker file镜像

目录 一、Docker镜像的创建 1、基于现有镜像创建 2、基于本地模版创建 3、基于Dockerfile创建 1、联合文件系统&#xff08;UnionFS&#xff09; ​编辑2、镜像加载原理 3、Dockerfile 4、Docker 镜像结构的分层 二、Dockerfile 操作常用的指令 &#xff08;1&#xf…

把树莓派改造成NAT软路由器

本文目录 1、查看网卡情况2、配置静态ip3、配置IP转发和SNAT功能3.1、开启Linux的报文转发功能 3.2、开启SNAT功能4、进阶配置4.1、如果WAN口(上行接口)eth0是动态分配的IP地址4.2、在LAN口上&#xff0c;给下游主机开启自动分配IP地址功能4.3、永久保存iptables, SNAT配置&…

Redis学习笔记02(主从同步,哨兵,哨兵集群)

数据同步&#xff1a;主从数据库如何保障数据一致性 redis具有高可靠性&#xff1a;1.数据尽量减少丢失&#xff08;AOF和RDB来保障&#xff09; 2.服务尽量减少中断.第二点通过增加冗余副本来保障。 读写分离&#xff1a; 减少保障数据一致性的开销。修改操作只会在主库上进…

《花雕学AI》解锁ChatGPT潜力!183个最佳提示语,助您充分利用人工智能技术

随着机器学习和自然语言处理技术的不断进步&#xff0c;人工智能在各个领域的应用越来越广泛。ChatGPT&#xff08;Generative Pre-trained Transformer&#xff09;是一个强大的自然语言生成模型&#xff0c;它可以帮助我们生成高质量的文本内容。本文为你列举了 183 种可能的…

【51单片机】DS1302时钟模块

&#x1f38a;专栏【51单片机】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Waiting For Love】 大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 目录 &#x1f354;效果 &#x1f354;代码 main.…

Stable Diffusion 本地部署教程不完全指南

ChatGPT免费体验入口网址 http://chat.xutongbao.top 参考链接&#xff1a; ERROR: Could not find a version that satisfies the requirement torch1.7.0 ERROR: No matching……_congcongiii的博客-CSDN博客 下载链接&#xff1a; https://download.pytorch.org/whl/cu11…

VMware下centos7开机登陆页面死循环问题解决

文章目录 VMware下centos7开机登陆页面死循环问题详细解决解决 VMware下centos7开机登陆页面死循环问题详细解决 脚本中有reboot重启命令 并且给该脚本加上了开机自启动 因为在脚本中没有给重启做判断&#xff0c;运行脚本后就会一直重启 解决 在VMware下centos7开机页面按e键…

【Linux】如何实现单机版QQ,来看进程间通信之管道

学会了管道&#xff0c;就可以实现简单的qq哦~ 文章目录 前言一、匿名管道总结 前言 为什么要进行进程间通信呢&#xff1f;因为需要以下这些事&#xff1a; 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 资源共享&#xff1a;多个进程之间共享同样的资源。 …

【五一创作】Linux---I2C应用编程

目录简述 前言&#xff1a; 一、I2C协议 &#xff08;1&#xff09;概述 &#xff08;2&#xff09;I2C硬件框架&#xff1a; &#xff08;3&#xff09;I2C软件框架 &#xff08;4&#xff09;I2C数据格式 二、SMBus协议 三、I2C系统重要的结构体 四、访问I2C设备&am…

欧姆龙NX/NJ系列PLC对接Oracle数据库,实现PLC与数据库双向数据通讯

智能网关IGT-DSER方便实现PLC与数据库之间的数据通讯&#xff0c;既可以读取PLC的数据上报到数据库&#xff0c;也可以从数据库查询数据后写入到PLC的寄存器。 网关安装在设备侧&#xff0c;与设备同时起停&#xff0c;不担心数据丢失&#xff1b;在断网、服务器维护上报数据有…

ID3算法报告理解笔记

专有名词解释&#xff1a; 决策树&#xff1a;决策树是根据已知若干条件&#xff0c;来对事件做出判断。从根节点到叶子结点。自上而下生成&#xff0c;每个决策或事件都可能引发两个或多个事件。将这些事件根据不同的特征进行划分&#xff0c;最后将类别分出&#xff0c;得到…

【Java校招面试】基础知识(四)——JVM

目录 前言一、基础概念二、反射三、类加载器ClassLoader四、JVM内存模型后记 前言 本篇主要介绍Java虚拟机——JVM的相关内容。 “基础知识”是本专栏的第一个部分&#xff0c;本篇博文是第四篇博文&#xff0c;如有需要&#xff0c;可&#xff1a; 点击这里&#xff0c;返回…

java 泛型知识整理

Java泛型这个特性是从JDK 1.5才开始加入的&#xff0c;因此为了兼容之前的版本&#xff0c;Java泛型的实现采取了“伪泛型”的策略&#xff0c;即Java在语法上支持泛型&#xff0c;但是在编译阶段会进行所谓的“类型擦除”&#xff08;Type Erasure&#xff09;&#xff0c;将所…

【网络协议详解】——GNS3的使用(学习笔记)

&#x1f4d6; 前言&#xff1a;在IT领域&#xff0c;网络协议的理解和掌握是至关重要的。GNS3和Wireshark是非常实用的工具&#xff0c;它们可以帮助你深入了解TCP/IP协议和网络的运作情况。 目录 &#x1f552; 1. 网络协议分析工具——GNS3&#x1f558; 1.1 快速上手&#…

磁盘和固态磁盘

磁盘和固态磁盘 磁盘的物理结构 ​ 磁盘的表面由一些磁性的物质组成&#xff0c;可以用这些磁性物质来记录二进制数据。磁盘的盘面被划分成一个个磁道&#xff0c;这样一个“圈”就是一个磁道。同一磁盘上不同磁道上记录的信息量相同&#xff0c;因此内侧磁道上的数据密度较大…

嵌入式C语言自我修养笔记1-ARM体系结构与编译运行

目录 ARM 体系结构ARM 体系结构ARM 汇编指令ARM 寻址方式ARM 伪指令C 与汇编混合编程 程序编译链接与安装运行预处理过程编译过程链接过程程序安装apt-get链接静态库动态链接共享库插件工作原理Linux 内核模块运行机制Linux 内核编译与启动分析 ARM 体系结构 ARM 体系结构 AR…

计算机基础书籍

一操作系统 二常见问题总结 1.操作系统的特征&#xff1f; 并发、共享、虚拟、异步性 2.进程阻塞与唤醒的条件 等待 I/O 操作完成请求系统资源失败等待信号量或事件等待子进程结束被高优先级进程抢占 3.如何避免死锁&#xff1f; 1、避免资源竞争 2、破坏循环等待条件 3、优…