【C++修行之路】类和对象

news2025/1/16 3:40:01

面向对象编程详解目录

  • 前言
  • 面向对象和面向过程
  • 类和结构体
  • 构造函数和析构函数
  • 拷贝构造和赋值重载
  • 结语

前言

好久不见,首先祝大家元宵节快乐,万家元夕宴,一路太平歌,今天执此佳节,一起来学习一下类和对象吧~

面向对象和面向过程

初学类和对象,我们不需要急切了解何为面向对象。在之后文章中会慢慢渗透。

我们只需要知道,面向对象更喜欢将一件事拆分为不同的对象即可

例如,洗衣服这件事,就可以拆分成人,洗衣机,洗衣粉,衣服这四个对象。

类和结构体

我们习惯用类(class)或结构体(struct)来定义上述 “对象”

C++中的结构体与C语言不一样,C++结构体支持在结构体内定义函数

因此在我看来结构体与类 本质上没有任何区别,只是结构体内定义的成员默认都是公有的(public)而类内定义的成员默认都是私有的(private)

public :可以在类外访问成员,即公有
private:只能在类内访问成员,即私有

  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止

  • 如果后面没有访问限定符,作用域就到 } 即类结束。

至于何时实用结构体,何时实用类,给出我个人的习惯,仅供参考~

结构体(struct):只存放变量
类(class):既存放变量,也存放成员函数时

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

class Enity
{
public:
	void func() {};
};

void Enity::func()
{

}

应当注意,类的实例化被称为对象,类相当于一张图纸,而对象相当于按照此图纸建造的房屋。

建造房屋的过程被称为 实例化

实例化后,对象才占用实际的物理空间
在这里插入图片描述
每一个被实例化出来的对象,只存有自己的成员变量,不会单独存有成员函数

既然不会单独存有成员函数,那怎么知道是谁调用了这个函数呢?

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

  1. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
  2. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。

使用了this指针,就能够做到共享成员函数,那么类的大小只存变量的大小即可,依然要按照内存对齐的原则计算。

若类内没有成员变量,系统会给实例化的对象分配一个字节占用空间!


构造函数和析构函数

构造函数与类同名,主要完成初始化对象的功能。
析构函数在类名加~,主要是完成对象中资源清理。

注意:析构函数不销毁对象本身,仅仅释放对象资源!

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

	~Date()
	{

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

对象在初始化的时候会自动调用构造函数,在对象生命周期结束前会自动调用析构函数。

若没有手动书写构造/析构函数,编译器会自动生成默认的构造/析构函数,如果书写,编译器就不会生成!

✔️默认生成的构造/析构函数,内置类型不做处理,自定义类型会调用对应的构造和析构函数。

如图默认生成的不对内置类型处理
因此一般我们采用两种方式替代默认构造函数

✔️ 全缺省构造函数,这样即使不传参,也能按照缺省值赋值
✔️C++11允许在类中为变量设置默认值

最后,构造函数是支持重载的,而析构函数只能有一个~


拷贝构造和赋值重载

🎶拷贝构造
C++类能制造出一个对象,也支持用这个对象去赋值另外一个对象,这就叫做拷贝构造。

拷贝构造是构造函数的一种,因此如果我们不自己书写,编译器会帮助我们自动生成。

✔️内置类型进行浅拷贝,直接拷贝过来。
✔️自定义类型则调用其拷贝构造。

拷贝构造只能传对象的引用,不能传值,会引发无穷递归。
传值为什么会无穷递归?
传值,并不是直接把对象传过去,要先把对象进行一次拷贝,而对象是自定义类型,要拷贝就要调用拷贝构造,但拷贝构造需要参数,参数又要进行拷贝。。。这样就引发了无穷递归

因此拷贝构造必须要传引用!!!

Date(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;

}

因为拷贝构造也是构造函数一种,如果不自己生成,系统也会自动生成

系统生成的拷贝构造虽然会进行拷贝,但浅拷贝会造成一系列问题

在这里插入图片描述
因此在设计内存空间的拷贝时,我们要重构拷贝构造,并且使用深拷贝。

class Stack
{
public:
	Stack(int capacity=0,int size=0)
	{
		_capacity = capacity;
		_size = size;
	}

	Stack(const Stack& d)
	{
		//实现深拷贝
		int* tmp = (int*)malloc(sizeof(int) * d._capacity);
		if (tmp == NULL) perror("error malloc");
		memcpy(tmp, d._a, sizeof(int) * d._capacity);
		_a = tmp;
	}
private:
	int* _a;
	int _capacity;
	int _size;
};

🎶赋值重载

赋值重载又叫赋值运算符,是将我们各种操作符进行重载的工具。

上述我们所讲的日期类中,我们期望能直接将两个日期进行比较,看看谁更大

date1 > date2 //即达到如下效果

但我们知道,只有内置类型可以比较,比如两个整形。

4 < 5//内置类型直接比较

使用操作符重载即可完成上述比较,下面我们来看一下运算符重载如何实现,以<为例

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

	bool operator<(const Date& d)
	{
		//运算符重载 < 号
		if (_year > d._year)
		{
			return false;
		}
		else if (_year == _year && _month > d._month)
		{
			return false;
		}
		else if (_year == _year && _month == d._month && _day > d._day)
		{
			return false;
		}
		return true;
	}
private:
	int _year = 0;
	int _month = 0;
	int _day = 0;
};

int main()
{
	Date d1(2023, 2, 5);
	Date d2(2023, 2, 3);

	cout << (d1 < d2) << endl;
}

大部分操作符都是可以重载,但要注意有五个操作符是不能重载的:
1 . (点运算符)

2 :: (域运算符)

3 .* (点星运算符)

4 ?: (条件运算符又叫三目运算符)

5 sizeof (计算大小)

以上五个操作符是不可以重载的!


结语

那么到这里,本篇文章就到此为止了,如果你觉得有所收获,可以给我一个 点赞+关注,这是对我最大的鼓励,我们下次见~

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

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

相关文章

系列分享 |《最强的 VLC 多媒体开发教程》

作者&#xff1a; 一去、二三里 个人微信号&#xff1a; iwaleon 微信公众号&#xff1a; 高效程序员 专栏介绍 《VLC 多媒体开发》&#xff0c;是一个专注于 libVLC 开发的专栏&#xff0c;里面共包含几十个章节&#xff0c;从 0 到 1&#xff0c;图文并茂&#xff0c;详细地…

【Linux】冯诺依曼体系与操作系统(OS)概念

文章目录冯诺依曼体系结构为什么是这样的结构局部性原理操作系统(Operator System)设计OS的目的定位如何理解管理 (精髓:先描述再组织)总结系统调用和库函数概念冯诺依曼体系结构 我们常见的计算机,如笔记本.我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系 为什么是这…

C++深入浅出(八)—— 继承

文章目录1. 继承的概念及定义&#x1f351; 继承的概念&#x1f351; 继承的定义&#x1f345; 定义格式&#x1f345; 继承关系和访问限定符&#x1f345; 继承基类成员访问方式的变化2. 基类和派生类对象赋值转换3. 继承中的作用域4. 派生类的默认成员函数5. 继承与友元6. 继…

jsp 校园网系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp 校园网系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统采用web模式开发&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数…

C#,入门教程(39)——C#语言的概念与知识点摘要

本文归纳整理C#的一些知识点&#xff0c;便于快速浏览与掌握C#语言的一些基本概念。本文并没有很好地层次与组织&#xff0c;抄了不少&#xff0c;写了不少&#xff0c;想到什么&#xff0c;就写什么。01 类 class类是C#等面向对象编程语言&#xff08;Object-oriented program…

常用API、Lambda、常见算法

目录 日期与时间 Date SimpleDateFormat Calendar JDK8新增日期类 概述、LocalTime/LocalDate/LocalDateTime Instant DateTimeFormatter Duration/Period ChronoUnit 包装类 包装类练习 正则表达式 正则表达式概述、初体验 正则表达式的匹配规则 正则表达式的…

Zookeeper注册中心

zookeeper的使用场景 分布式协调、分布式锁、元数据/配置信息管理、HA高可用性 分布式协调 A系统发送个请求到mq,然后B系统消息消费之后处理了,那A系统如何知道B系统的处理结果?A系统发送请求之后在zookeeper上对某个节点的值注册个监听器,一旦B系统处理完了就修改zooke…

C语言高级教程-C语言数组(七):数组综合实例之井字棋游戏问题

C语言高级教程-C语言数组&#xff08;七&#xff09;&#xff1a;数组综合实例之井字棋游戏问题一、本文的编译环境二、井字棋游戏的问题三、井字棋游戏的分析四、井字棋游戏的程序编写步骤4.1、添加主要的游戏循环和显示这个方格4.2、让玩家选择-一个方格&#xff0c; 并确定那…

Android 设置可抓包

在ren目录下新建xml文件夹&#xff0c;在xml下新建network_security_config.xml<?xml version"1.0" encoding"utf-8"?><!--<network-security-config>--><!-- <base-config cleartextTrafficPermitted"true" />--&…

MySQL面试:MySQL事务,内附详细视频教程,以及sql事务演示

文章目录一、事务&#xff08;提出事务&#xff09;二、四个特性&#xff08;事务要实现的特性&#xff09;三、一致性问题&#xff08;事务可以解决这些问题&#xff09;四、解决&#xff08;事务解决部分或全部一致性问题&#xff09;五、实现&#xff08;事务实现ACID的机制…

Python setattr()、getattr()、hasattr()函数用法详解

Python hasattr()函数hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法。该函数的语法格式如下&#xff1a;hasattr(obj, name)其中 obj 指的是某个类的实例对象&#xff0c;name 表示指定的属性名或方法名。同时&#xff0c;该函数会将判断的结果&#xff0…

差值结构不对称部分的约化质心

( A, B )---5*30*2---( 1, 0 )( 0, 1 ) 做一个网络&#xff0c;输入为5个点&#xff0c;训练集A,B各有两张图片。让B的两张图片全是0.排列组合A&#xff0c;记录迭代次数平均值的变化。 迭代了1024组&#xff0c;共收集到33组不同的数据&#xff0c;其中对称的部分有17组&…

Java volatile学习

面试题&#xff1a; 1、请谈谈你对volatile的理解&#xff1f; volatile是Java虚拟机提供的轻量级的同步机制1.保证可见性2.不保证原子性3.禁止指令重排 2、JMM你谈谈?3、你在哪些地方用到过volatile?一、概述 JMM(Java内存模型 Java Memory Model&#xff0c;简称JMM) 本身是…

JSP 概述(三)

JSP 的处理过程&JSP 与其他服务器端脚本语言的比较1. JSP 的处理过程2. JSP 与其他服务器端脚本语言的比较2.1 CGI2.2 ASP2.3 PHP2.4 ASP.NET结束语1. JSP 的处理过程 当客户端浏览器向服务器发出请求要访问一个 JSP 页面时&#xff0c;服务器根据该请求加载相应的 JSP 页…

微信小程序里面的js文件分为哪几类?

1.小程序中的.js的分类 小程序中的JS文件分为三大类&#xff0c;分别是&#xff1a; 1.app.js 是整个小程序项目的入口文件&#xff0c;通过调用App()函数来启动整个小程序 2.页面的.js文件 是页面的入口文件&#xff0c;通过调用 Page&#xff08;&#xff09;函数来创建并运行…

Java基础语法(基础篇 适合小白)

Hello World public 访问修饰符 static 关键字 void 返回类型 String 类 args字符串数组 public class HelloWorld {/* 第一个Java程序* 它将输出字符串 Hello World*/public static void main(String[] args) {System.out.println("Hello World"); // 输出 Hello Wo…

Odoo | 7个步骤搭建的“在线表格组件”,十分丝滑~

X-SpreadSheet是一个类似于google sheet的在线表格组件&#xff0c;很多场景都能借助它来搭建在线表格。 集成过程 1、下载X-SpreadSheet源码到本地 下载地址 x-spreadsheet.css&#xff1a; https://unpkg.com/x-data-spreadsheet1.0.13/dist/xspreadsheet.css x-spread…

Tomcat的安装及配置

Tomcat介绍&#xff1a;Tomcat简单地说就是一个运行JAVA的网络服务器&#xff0c;底层是Socket的一个程序&#xff0c;它也是JSP和Serlvet的一个容器疑问&#xff1a;一个电脑中可以安装多个版本的Tomcat吗&#xff1f;同一台电脑可以同时安装多个Tomcat服务器。安装及配置&…

【Spark分布式内存计算框架——Spark 基础环境】2. 快速入门(上)环境准备

第三章 快速入门 目前Spark最新稳定版本&#xff1a;2.4.x系列&#xff0c;官方推荐使用的版本&#xff0c;也是目前企业中使用较多版本&#xff0c;网址&#xff1a;https://github.com/apache/spark/releases Spark 2.4.x依赖其他语言版本如下&#xff0c;其中既支持Scala …

代码随想录算法训练营第三十一天_第八章_贪心算法 | 理论基础、455.分发饼干、376. 摆动序列、53.最大子数组和

理论基础 LeetCode 455.分发饼干 视频讲解https://www.bilibili.com/video/BV1MM411b7cq/?spm_id_from333.788&vd_sourcef98f2942b3c4cafea8907a325fc56a48文章讲解https://programmercarl.com/0455.%E5%88%86%E5%8F%91%E9%A5%BC%E5%B9%B2.html 思路&#xff1a;代码&…