【C++】— 类和对象(2)

news2024/9/29 7:00:25

文章目录

    • 💞1.类的默认成员函数
    • 💞2.构造函数
    • 💞3.析构函数
    • 💞4.拷贝构造函数
    • 💞5.赋值运算符重载
      • 💞5.1 运算符重载
      • 💞5.2 赋值运算符重载
    • 💞6.取地址运算符重载
      • 💞6.1const成员函数
      • 💞6.2 取地址运算符重载

💞1.类的默认成员函数

默认成员函数是用户没有显示的写而编译器自动生成的函数,一个类,我们不写编译器会默认生成6个默认成员函数。
在这里插入图片描述

💞2.构造函数

构造函数是特殊的成员函数。虽然名叫构造函数,但是它的主任务并不是开空间创建对象,而是对象实例化时初始化对象。 相当于Stack中的Init函数.

📌构造函数的特点:
(1)函数名与类名相同
(2)没有返回值
(3)对象实例化时系统会自动调用对应的构造函数
(4)构造函数可以重载
(5)如果没有显示定义构造函数,编译器会自动生成一个无参的构造函数,如果显式写了,编译器将不再自动生成
(6)无参构造函数全缺省构造函数编译器自动生成的构造函数都叫做默认构造函数。需要注意的是有且只有一个存在,不能同时存在。✏️总结:不传实参调用的构造就叫默认构造
(7)编译器默认生成的构造函数对内置类型成员变量的初始化没有要求。对自定义类型成员变量,要求调用这个成员变量的默认构造函数初始化。若没有默认构造函数编译器就会报错。要初始化这个成员变量就要用初始化列表来初始化。初始化列表在后面的章节我们会讲

🔖内置类型: 语言提供的原生数据类型,如int /char/double/指针
🔖 自定义类型: 我们使用的class/struct 等关键字自己定义的类型

class Date
{
public:
	//1.无参构造函数
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}

	//2.带参构造函数
	Date(int year,int month,int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	 
	//3.全缺省构造函数
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;

};

💞3.析构函数

析构函数并不是完成对对象本身的销毁,C++中规定对象在销毁时会自动调用析构函数,完成对象中资源的清理和释放工作。析构函数就类似Stack中的Destroy功能。

📌析构函数的特点:
(1)析构函数的函数名是在类名前**+** ~
(2)无参数无返回值(和构造函数类似)
(3)对象生命周期结束时会自动调用对应的析构函数
(4)跟构造函数类似,我们不写编译器自动生成的析构函数对内置类型成员不做处理,对自定义类型成员对调用它的析构函数
(5)自定义类型成员无论什么时候都对调用它的析构函数

#include<iostream>

using namespace std;
typedef int STDataType;
class Stack
{
public:
	//构造函数
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (_a == nullptr)
		{
			perror("malloc fail");
			return;
		}

		_capacity = n;
		_top = 0;
	}
	//析构函数
	~Stack()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}

private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};

//两个队列实现栈
class MyQueue
{
	//编译器默认生成MyQueue的析构函数调用了Stack的析构,释放Stack内部的资源
	/*~MyQueue()
	{
	
	}*/
private:
	Stack pushst;
	Stack popst;
};
int main()
{
	Stack st;
	MyQueue mq;

	return 0;
}

💞4.拷贝构造函数

若一个构造函数的第一个参数是自身类类型的引用,且任何额外的参数都有默认值(缺省值),则此函数叫做拷贝构造函数。也就是说拷贝构造是一个特殊的构造函数

📌拷贝构造函数的特点:
(1)拷贝构造函数是构造函数的重载
(2)拷贝构造函数的第一个参数必须是类类型对象的引用,使用传值的方式就会陷入无穷递归中,编译器就会报错。拷贝构造允许有多个参数,但第一个参数必须是类类型的引用,后面的参数必须有缺省值。
(3)C++规定自定义类型对象进行传值传参时必须调用拷贝构造,所以自定义类型进行传值传参和传值返回都会调用拷贝构造来完成。
(4)如果未显式写拷贝构造函数,编译器会自动生成拷贝构造函数。自动生成的拷贝构造函数对内置类型成员变量会完成值拷贝/浅拷贝(一个字节一个字节拷贝),对自定义成员变量会调用它的拷贝构造函数。
(5)像Date这样的成员变量都是内置类型并且没有指向什么资源,编译器自动生成的拷贝构造函数就可以完成需要的拷贝,所以不需要我们显示实现拷贝构造。像Stack这样的类,_a指向了资源,编译器自动生成的拷贝构造是浅拷贝不符合我们的需求,所以需要我们自己完成深拷贝(对指向的资源也进行拷贝)。像MyQueue这样的的类型内部也是Stack的成员,编译器自动生成的拷贝构造会调用Stack的拷贝构造,不需要我们实现MyQueue的拷贝构造。✏️总结:如果一个类显示实现了析构并释放了资源,那么它就需要写拷贝构造,否则不需要。
(6)传值返回会产生一个临时对象调用拷贝构造,但传引用返回,返回的是引用对象的别名,没有产生拷贝。但是如果传引用返回返回的是一个当前函数局部域的局部对象,函数结束返回值就销毁了,这时的引用相当于一个野指针。✏️所以:传引用返回一定要确保返回对象在函数结束后还在,才能用引用返回。

#include<iostream>

using namespace std;

class Date
{
public:
	Date(int year = 1,int month = 1,int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造函数
	Date(Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	//虽然可以传参但不是拷贝构造
	/*Date(Date* d)
	{
		_year = d->_year;
		_month = d->_month;
		_day = d->_day;
	}*/

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



int main()
{
	Date d1(2024,9,27); //C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,这里传值传参要调用拷贝构造
	Date d2(d1);
	Date d2 = d1;//这两种写法都是可以的,也都是拷贝构造
	

	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

💞5.赋值运算符重载

💞5.1 运算符重载

🌵当运算符被用到类类型对象时,C++允许我们用运算符进行重载的形式指定新的定义。C++规定当类类型使用运算符时必须对运算符进行重载。若没有运算符重载,编译器就会报错。

🌵运算符重载是具有特殊名字的函数,由operator和后面要定义的运算符共同构成。

🌵重载运算符函数的参数的个数和该运算符作用的对象个数一样多(比如a+b,+的作用对象是a和b所以+运算符重载函数有两个参数)
🌵一个重载运算符函数如果是成员函数,那么它的第一个运算对象传给隐式地this指针,因此运算符重载作为成员函数时,参数比运算对象少一个。
🌵运算符重载后,其优先性和结合性与内置类型一样。

🌵.* ,::,sizeof,?:,. 这几个运算符不能重载。
🌵operator++默认为前置++,后置++给operator++增加一个int的形参,与前置++构成函数重载。

🌵重载<<>>时,需要重载为全局函数,因为重载为成员函数,this指针抢了第一个形参位置,而第一个形参调用的是左侧对象,调用时就成了对象<<cout,不符合使用习惯和可读性。重载为全局函数把ostream/istream放到第一个形参位置就行了。

#include<iostream>

using namespace std;


class Date
{
public:
	//成员函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//<的重载函数
	bool operator<(const Date& d)
	{
		if (_year < d._year)
		{
			return true;
		}
		else if (_year == d._year && _month < d._month)
		{
			return true;
		}
		else if (_year == d._year && _month == d._month && _day < d._day)
		{
			return true;
		}

		return false;
	}
private:
	//成员变量
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1(2024, 9, 27);
	Date d2(2024, 10, 1);
	
	cout << d1.operator<(d2) << endl;

	return 0;
}

运行结果:
在这里插入图片描述

💞5.2 赋值运算符重载

赋值运算符重载是一个默认成员函数,用于两个已经存在的对象的直接拷贝赋值。而拷贝构造是一个对象拷贝初始化给另一个要创建的对象。

📌赋值运算符重载的特点:
🌵赋值运算符重载是运算符重载,并且规定重载为成员函数。赋值运算符重载的参数建议写成const+类类型的引用,否则会传值传参会有拷贝
🌵有返回值,并且建议写成当前类类型的引用,引用返回可以提高效率,有返回值是为了支持连续赋值。
🌵没有显示实现时,编译器会默认生成一个默认赋值运算符重载,默认赋值运算符对内置类型完成值拷贝/浅拷贝对自定义类型成员会调用它的赋值重载函数
🌵像Date这样的类成员变量全是内置类型没有指向什么资源,编译器自动生成的赋值运算符重载就可以完成我们需要的拷贝,所以不需要我们显示实现赋值运算符重载。而像Stack这样的类,_a指向了内部资源,编译器自动生成的赋值运算符重载完成的是值拷贝/浅拷贝不符合我们的要求,所以需要我们自己实现**深拷贝。**像MyQueue这样的自定义类型,内部时Stack的成员,编译器自动生成的赋值运算符重载会调用Stack的赋值运算符重载。✏️总结:如果一个类显示实现了析构并释放了资源,那么它就需要显示写赋值运算符重载。

#include<iostream>

using namespace std;


class Date
{
public:
	//成员函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	//赋值运算符重载
	Date& operator=(const Date& d)//有返回值是为了支持连续赋值
	{
		if (this != &d)//判断是否为自己给自己赋值
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	
	}
private:
	//成员变量
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1(2024, 9, 27);
	Date d2;

	d2.operator=(d1);

	d1.Print();
	d2.Print();

	return 0;
}

在这里插入图片描述

💞6.取地址运算符重载

💞6.1const成员函数

const修饰的成员函数称为const成员函数。const修饰成员函数const放到成员函数的后面。
const修饰成员函数其实修饰的是成员函数的this指针,表示该成员函数中不能对类的成员进行修改。

const修饰Date类的Print函数时,Print隐含的this指针由Date* const this变成了const Date* const this

#include<iostream>
using namespace std;

class Date
{
public:
	//成员函数
	//构造函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	
	//void Print(const Date* const this)
	void Print() const //const放在成员函数的后面。const修饰的不是this本身,而是this指向的内容
	{
		cout << _year << "-" << _month << "-" << _day << endl;

	}
private:
	//成员变量
	int _year;
	int _month;
	int _day;
};


int main()
{
	//非const对象也可以调用const成员函数是一种权限的缩小
	Date d1(2024, 9, 27);
	d1.Print(); 

	Date d2;
	d2.Print();

	return 0;
}

💞6.2 取地址运算符重载

取地址运算符重载分为普通的取地址运算符重载和被const修饰的取地址运算符重载。一般编译器自动生成的就够我们用了,不需要去显示实现。除非我们不想让别人知道当前类对象的地址。

class Date
{

public:
	Date* operator&()//普通对象调用普通版本
	{
		return this;
		//return 0x222232   不想让别人取到当前类的地址,胡乱返回一个
	}

	const Date* operator&()const //const对象调用const版本
	{
		return this;
		//return nullptr;
	}
private:
	int _year;
	int _month;
	int _day;
};

如果不显示写这样也可以取到地址,原因是取地址运算符重载是默认成员函数,不写编译器会默认生成。

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

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

相关文章

中国算力大会启幕,联想发布异构智算产业创新成果

9月27日&#xff0c;2024中国算力大会在河南郑州拉开帷幕。作为全球领先的算力基础设施和服务提供商&#xff0c;联想集团参会参展并携手异构智算产业联盟承办2024异构智算产业生态联盟技术论坛。 据「TMT星球」了解&#xff0c;论坛发布了新一代AI服务器、AI应用部署解决方案…

如何用AI完成毕业论文

一、利用 AI 辅助资料收集 AI 可以帮助你快速搜索大量与毕业论文相关的资料&#xff0c;节省时间和精力。 writehelp智能写作辅导&#xff1a;http://www.writehelp.vip/?sid17&#xff0c;限时免费提供开题报告、任务书和答辩PPT。 二、借助 AI 生成提纲 它能根据你的研究主…

【C++】继承,菱形继承,虚拟继承,组合详解

目录 1. 继承概念与定义 1.1 概念 1.2 定义 2. 父类与子类的赋值规则 3. 继承的作用域 4. 子类的默认成员函数 5. 继承与友元 6. 继承与静态成员 7. 菱形继承 7.1 继承关系 7.2 菱形继承的问题 7.3 虚拟继承 8. 继承与组合 1. 继承概念与定义 1.1 概念 1. 继承&a…

基于SpringCloud的微服务架构下安全开发运维准则

为什么要进行安全设计 微服务架构进行安全设计的原因主要包括以下几点&#xff1a; 提高数据保护&#xff1a;微服务架构中&#xff0c;服务间通信频繁&#xff0c;涉及到大量敏感数据的交换。安全设计可以确保数据在传输和存储过程中的安全性&#xff0c;防止数据泄露和篡改。…

物联网迎来下半场,国产 IoTOS 打造企业级智能硬件云服务平台

如有需求&#xff0c;文末联系小编 氦氪云 IoTOS 是一套先进的企业级物联网解决方案平台&#xff0c;为万物互联提供可靠安全稳定的终端接入、协议适配、消息路由、数据存储和分析、应用使能等核心功能。面向物联网领域中的终端设备商、系统集成商、应用服务商、能力提供商等&a…

定积分中静水压力问题

静水压力与定积分 静水压力问题是定积分在物理学中的一个重要应用。它利用积分的思想&#xff0c;将一个复杂的、连续变化的压力分布问题转化为一系列微小压力单元的累加&#xff0c;最终求出总压力。 基本原理&#xff1a; 静水压力是指静止液体对浸在其中的物体表面所施加…

BUG——IMX6ULL编译正点原子Linux内核报错

最初编译的是正点原子改过的Linux内核&#xff0c;可能是版本问题&#xff0c;一直报错&#xff0c;无法成功编译。然后换成NXP官方Linux内核6.6版本&#xff0c;初始编译虽然也报各种错&#xff0c;但都是缺少库或相关工具&#xff0c;全部安装后就可以成功编译出镜像了&#…

【RocketMQ】MQ与RocketMQ介绍

&#x1f3af; 导读&#xff1a;本文介绍了消息队列&#xff08;MQ&#xff09;的基本概念及其在分布式系统中的作用&#xff0c;包括实现异步通信、削峰限流和应用解耦等方面的优势&#xff0c;并对ActiveMQ、RabbitMQ、RocketMQ及Kafka四种MQ产品进行了对比分析&#xff0c;涵…

【Canvas与诗词】秋夕.杜牧(银烛秋光冷画屏......)

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>金六边形外圈绿色底录杜牧秋夕诗</title><style type"…

Unity实战案例全解析:RTS游戏的框选和阵型功能(1) 基础要素

本案例来源于unity唐老狮&#xff0c;有兴趣的小伙伴可以去泰克在线观看该课程 【唐老狮】Unity实现 即时战略游戏 阵型功能 - 泰课在线 -- 志存高远&#xff0c;稳如泰山 - 国内专业的在线学习平台|Unity3d培训|Unity教程|Unity教程 Unreal 虚幻 AR|移动开发|美术CG - Powered…

【CTF Web】Pikachu 反射型xss(get) Writeup(反射型XSS+GET请求)

XSS&#xff08;跨站脚本&#xff09;概述 Cross-Site Scripting 简称为“CSS”&#xff0c;为避免与前端叠成样式表的缩写"CSS"冲突&#xff0c;故又称XSS。一般XSS可以分为如下几种常见类型&#xff1a; 1.反射性XSS; 2.存储型XSS; 3.DOM型XSS; XSS漏洞一直被评估…

Java基于easyExcel的自定义表格格式

这里用的到easyExcel版本为3.3.4 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.4</version></dependency> 效果 代码部分 package com.tianyu.test;import com.alibaba.exc…

全网最适合入门的面向对象编程教程:54 Python字符串与序列化-字符串格式化与format方法

全网最适合入门的面向对象编程教程&#xff1a;54 Python 字符串与序列化-字符串格式化与 format 方法 摘要&#xff1a; 在 Python 中&#xff0c;字符串格式化是将变量插入到字符串中的一种方式&#xff0c;Python 提供了多种字符串格式化的方法&#xff0c;包括旧式的 % 格…

BFS之最短路径模型

当一个图的每个边的权重都一样的时候&#xff0c;会有一个最短路径模型。不需要考虑边的影响。 1076. 迷宫问题 - AcWing题库 #include<iostream> #include<queue> #include<utility> #include<algorithm> #include<stack> using namespace std…

C语言课程设计题目七:学生成绩管理系统设计

题目七&#xff1a;学生成绩管理系统设计 学生成绩信息包括&#xff1a;学期&#xff0c;学号&#xff0c;班别&#xff0c;姓名&#xff0c;四门课程成绩(语文、数学、英语和计算机)等。 主要功能&#xff1a; 能按学期、按班级完成对学生成绩的录入、修改。能按班级统计学生…

力扣最热一百题——颜色分类

目录 题目链接&#xff1a;75. 颜色分类 - 力扣&#xff08;LeetCode&#xff09; 题目描述 示例 提示&#xff1a; 解法一&#xff1a;不要脸用sort Java写法&#xff1a; 运行时间 解法二&#xff1a;O1指针 Java写法&#xff1a; 重点 运行时间 C写法&#xff1a;…

Python库matplotlib之二

Python库matplotlib之二 figureAxessubplot figure matplotlib.pyplot.figure(numNone, figsizeNone, dpiNone, facecolorNone, edgecolorNone, frameonTrue, FigureClass<class ‘matplotlib.figure.Figure’>, clearFalse, **kwargs) num&#xff0c;int 或 str 或 fi…

Starfyre:一款使用纯 Python 创建响应式前端应用的 Python Web 框架

Starfyre 是一款基于 WebAssembly (WASM) 的 Python Web 框架&#xff0c;它允许你使用纯 Python 创建响应式前端应用。这意味着你可以轻松地构建交互式、实时应用程序&#xff0c;无需繁琐的 JavaScript 代码。Starfyre 基于 Pyscript 实现客户端功能&#xff0c;并通过 pyxid…

【每天学个新注解】Day 9 Lombok注解简解(八)—@Synchronized、@Locked

Synchronized 通过锁代码块的方式实现同步锁。 当synchronized修饰类属性时&#xff0c;通常用于定义同步代码块&#xff0c;此时需要指定一个锁对象。这个锁对象通常是类的某个私有静态成员变量&#xff0c;因为类属性是静态的&#xff0c;所以锁也应该是静态的&#xff0c;以…

【Python】YOLO牛刀小试:快速实现视频物体检测

YOLO牛刀小试&#xff1a;快速实现视频物体检测 在深度学习的众多应用中&#xff0c;物体检测是一个热门且重要的领域。YOLO&#xff08;You Only Look Once&#xff09;系列模型以其快速和高效的特点&#xff0c;成为了物体检测的首选之一。本文将介绍如何使用YOLOv8模型进行…