C++——类模板经典案例——自定义通用数组类

news2024/11/13 6:47:08

案例:自定义数组类
需求:
1,对内置数据及自定义数据类型的数据存储
2,将数组中的数据存储到堆区
3,构造函数中可以存入数组的容量
4,提供对应的拷贝构造函数和=运算符重载防止浅拷贝问题的发生
5,提供尾插法和尾删法对数组中的数据进行增加和删除
6,提供下标的方式访问数组中的元素
7,获取数组中当前元素个数和数组的容量

代码的注释写的很详细了,个人觉得没啥好解释的,认真看看,都能看懂,很经典的案例,值得学习!!!

一、yy_Array.hpp

yy_Array.hpp文件包括:自定义数组类以及类的成员函数、构造函数、析构函数等相应实现

//防止头文件重复包含
#pragma once

#include<iostream>
template<class T>
class yy_Array 
{
public:
	yy_Array(int capacity)//有参构造函数,传入数组初始的容量
	{
		std::cout << "有参构造" << std::endl;
		this->capacity_ = capacity;
		this->size_ = 0; //数组刚开始一个元素都没有
		this->p_address_ = new T[this->capacity_];//开辟一块堆区空间,大小为数组的容量
	}

	//拷贝构造(为例防止堆区带来的浅拷贝问题)
	//若属性有在堆区开辟的,一定要用自己的拷贝构造函数,防止系统默认使用浅拷贝带来的问题
	//这里需要在堆区开辟数组,故有在堆区开辟的属性,需要使用自己的拷贝构造函数
	yy_Array(const yy_Array& arr) 
	{
		std::cout << "拷贝构造" << std::endl;
		this->capacity_ = arr.capacity_;
		this->size_ = arr.size_;
		this->p_address_ = new T[arr.capacity_]; //因为是堆内存,要重新开辟空间,深拷贝

		//若数组中本身就有数据,在深拷贝时,也需要拷贝过来
		for (int i = 0; i < this->size_; i++) 
		{
			this->p_address_[i] = arr.p_address_[i];
		}
	}


	//赋值运算符重载operator =,也是为了防止浅拷贝问题
	yy_Array& operator=(const yy_Array& arr) //返回本身,因为实际系统的赋值运算符支持a=b=c
	{
		std::cout << "运算符重载operator=" << std::endl;
		//先判断原来堆区中是否有数据,若事前有数据,先释放掉
		if (this->p_address_ != NULL) 
		{
			delete[] this->p_address_;//释放这个指向数组的指针
			this->p_address_ = NULL;//指针置空,防止野指针
			this->capacity_ = 0;
			this->size_ = 0;
		}

		//开始进行深拷贝,从堆区开辟内存
		this->capacity_ = arr.capacity_;
		this->size_ = arr.size_;
		this->p_address_ = new T[arr.capacity_]; //因为是堆内存,要重新开辟空间,深拷贝

		//若数组中本身就有数据,在深拷贝时,也需要拷贝过来
		for (int i = 0; i < this->size_; i++)
		{
			this->p_address_[i] = arr.p_address_[i];
		}

		return *this;//返回自身
	}

	//尾插法
	void Push_Back(const T& val) 
	{
		//若容量已经满了,提示再插入
		if (this->capacity_ == this->size_) 
		{
			std::cout << "数组已满" << std::endl;
			return;
		}
		else 
		{
			this->p_address_[this->size_] = val;//传入的val插到数组最后一个
			this->size_++;//插入一个元素,数组大小要进行更新
		}
	}


	//尾删法
	void Pop_Back()//删除操作不需要传参,直接把最后一个元素干掉即可,也就是让用户访问不到即可
	{
		//要进行尾删法,首先数据中必须有元素
		if (this->size_ == 0) 
		{
			std::cout << "数组已为空" << std::endl;
			return;
		}
		else 
		{
			this->size_--;//用户访问不到最后一个元素即可
		}
	}


	//通过小标的方式进行访问数组中的元素
	//因为是自己写的模板数组,单纯的a[0]是无法进行访问的,故需要重新对[]运算符进行重载
	T& operator[](int index) 
	{
		return this->p_address_[index];
	}

	//返回数组的容量
	int getCapacity() 
	{
		return this->capacity_;
	}

	//返回数据的大小
	int getSize() 
	{
		return this->size_;
	}


	~yy_Array()//析构函数
	{
		if (p_address_ != NULL) 
		{
			std::cout << "析构函数" << std::endl;
			delete[] this->p_address_;//释放这个指向数组的指针
			this->p_address_ = NULL;//指针置空,防止野指针
		}
	}


private:
	T* p_address_; //指针指向堆区开辟的真实数组
	int capacity_;//数组的容量,即数组最多存放多少元素
	int size_;//数组当前有多少个元素
};

二、array.cpp

主函数入口,分成三个函数(test1()、test2()以及test3())进行不同功能的测试
调试学习时,将主函数中test1()test2()test3()挨个取消注释,运行单个测试函数进行学习

#include <iostream>
#include "yy_Array.hpp"

void printIntArr(yy_Array<int>& arr) //打印输出数组内的元素
{
	for (int i = 0; i < arr.getSize(); i++) 
	{
		std::cout << arr[i] << std::endl;
	}
}

void test1() 
{
	yy_Array<int>yy_arr_1(5);//测试 有参构造函数 和 析构函数

	yy_Array<int>yy_arr_2(yy_arr_1);//测试 拷贝构造函数 和 析构函数

	yy_Array<int> yy_arr_3(100);//测试 有参构造 和 析构函数
	yy_arr_3 = yy_arr_1;//测试 运算符重载operator= 和 析构函数
}

void test2() 
{
	yy_Array<int>yy_arr_1(10);//测试 有参构造函数 和 析构函数
	//测试尾插法,利用尾插法向数组中插入数据
	for (int i = 0; i < 10; i++) 
	{
		yy_arr_1.Push_Back(i);
	}
	std::cout << "yy_arr_1的元素为:" << std::endl;
	printIntArr(yy_arr_1);
	//测试数组容量
	std::cout << "yy_arr_1的容量为:" << yy_arr_1.getCapacity() << std::endl;
	//测试数组大小
	std::cout << "yy_arr_1的目前大小为:" << yy_arr_1.getSize() << std::endl;


	yy_Array<int>yy_arr_2(yy_arr_1);//测试 拷贝构造函数 和 析构函数
	std::cout << "yy_arr_2的元素为:" << std::endl;
	printIntArr(yy_arr_2);
	//测试数组容量
	std::cout << "yy_arr_2的容量为:" << yy_arr_2.getCapacity() << std::endl;
	//测试数组大小
	std::cout << "yy_arr_2的目前大小为:" << yy_arr_2.getSize() << std::endl;
	
	//测试尾删法
	yy_arr_2.Pop_Back();
	//测试数组容量
	std::cout << "yy_arr_2尾删后的容量为:" << yy_arr_2.getCapacity() << std::endl;
	//测试数组大小
	std::cout << "yy_arr_2尾删后的目前大小为:" << yy_arr_2.getSize() << std::endl;
}




//测试自定义数据类型
class Beyond 
{
public:
	Beyond() {};//无参构造函数
	Beyond(std::string name, int age)
	{
		this->name_ = name;
		this->age_ = age;
	}
	std::string name_;
	int age_;
};
//输出自定义数据类型
void printBeyondArr(yy_Array<Beyond>& arr)
{
	for (int i = 0; i < arr.getSize(); i++)
	{
		std::cout << "姓名:" << arr[i].name_ << "年龄:" << arr[i].age_ << std::endl;
	}
}
void test3() 
{
	yy_Array<Beyond> arr(5);
	Beyond hjj("黄家驹", 31);
	Beyond hjq("黄家强", 56);
	Beyond hgz("黄贯中", 57);
	Beyond ysr("叶世荣", 58);

	//将数据通过尾插法插入到数组中
	arr.Push_Back(hjj);
	arr.Push_Back(hjq);
	arr.Push_Back(hgz);
	arr.Push_Back(ysr);

	//输出数组数据
	printBeyondArr(arr);

	//测试数组容量
	std::cout << "arr的容量为:" << arr.getCapacity() << std::endl;
	//测试数组大小
	std::cout << "arr的目前大小为:" << arr.getSize() << std::endl;
}


int main(int argc, char* argv[])
{
	test1();
	test2();
	test3();
	return 0;
}

三、测试结果

在这里插入图片描述

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

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

相关文章

户外上网黑科技|300~500元随身wifi测评推荐,华为vs格行vs中兴vs上赞,哪个好?

1.老牌国货&#xff0c;颜值担当——华为 设备价格&#xff1a;499元 套餐价格&#xff1a;99一个月 599一年 质保时间&#xff1a;1年 测评&#xff1a;网速大概在50~60M/S&#xff0c;华为是老牌国货了&#xff0c;设备上没有硬伤&#xff0c;家里连接多设备都没什么问…

小怡分享之Java中的异常

前言&#xff1a; &#x1f308;✨之前小怡带大家认识了String类&#xff0c;今天小怡给大家分享Java中的异常。 1.异常的概念与体系结构 1.1 异常的概念 在日常开发中&#xff0c;绞尽脑汁将代码写的尽善尽美&#xff0c;在程序运行中&#xff0c;难免会出现一些奇奇怪怪…

Python学习(2):在单机机器学习,使用Dask实现鸢尾数据集 Iris 的分类任务

目录 一、源码来源 二、鸢尾花数据集的品种分类 1、数据处理步骤 &#xff08;1&#xff09;数据集加载 &#xff08;2&#xff09;准备特征和标签 &#xff08;3&#xff09;训练集和测试集划分 2、安装必需的软件包 3、运行程序 三、信用卡欺诈数据集检测信用卡交易…

全网最详细的LVS实战详解

一、Lvs-nat实战部署 1、准备 设置好网卡信息 2、基础环境搭建详情 ①调度器LVS:网卡ens160(NAT模式)、网卡ens224(仅主机模式)&#xff0c;使其可处于不同的VLAN段 为网卡ens160设置IP vmset.sh ens160 172.25.254.100 lvs.zf.org为网卡ens224设置IP vmset.sh ens224 192.…

在MAC安装Lazarus 起点 - 我们的第一个Lazarus程序!

安装Lazarus 首先到Lazarus官网&#xff0c;找到合适的版本下载页面&#xff0c;比如Mac的版本&#xff1a; https://sourceforge.net/projects/lazarus/files/Lazarus%20macOS%20x86-64/Lazarus%203.4/ 将三个文件都下载到本地&#xff0c;需要安装这三个文件&#xff1a; …

Python学习(1):使用Python的Dask库实现并行计算

目录 一、Dask介绍 二、使用说明 安装 三、测试 1、单个文件中实现功能 2、运行多个可执行文件 最近在写并行计算相关部分&#xff0c;用到了python的Dask库。 Dask官网&#xff1a;Dask | Scale the Python tools you love 一、Dask介绍 Dask是一个灵活的并行和分布式…

C语言 ——— 学习并使用字符分类函数

目录 学习isupper函数 学习isdigit函数 学习tolower函数 将输入的字符串中把大写字母转换为小写字母并输出 学习isupper函数 参数部分&#xff1a; 形参需要传递的是一个字母&#xff0c;字符在ASCII码表上是以整型存储的&#xff0c;所以实参部分用(int c)没有问题 返回…

HarmonyOS笔记3:从网络数据接口API获取数据

面向HarmonyOS的移动应用一般采用MVVM模式&#xff08;见参考文献【1】&#xff09;&#xff0c;其中&#xff1a; M&#xff08;Model层)&#xff1a;模型层&#xff0c;存储数据和相关逻辑的模型。它表示组件或其他相关业务逻辑之间传输的数据。Model是对原始数据的进一步处理…

享界S9别乱选,定价有大玄机!

文 | AUTO芯球 作者 | 雷慢 享界S9刚上市&#xff0c; 就有人傻钱多、工作忙的老大哥来问我&#xff0c; 两个版本怎么选&#xff1f; 这不巧了吗&#xff0c;论华为车系&#xff0c;我是资深用户&#xff0c; 常开问界M9&#xff0c;试过智界S7&#xff0c;问界M7&#x…

PUA自己到无法自拔,或许是你过度信奉【优绩主义】

本文算是人文社科心理篇的第二期&#xff0c;不时发一些【理性】的【鸡汤】&#xff0c;或许对你认识社会本质有所帮助~ 一.定义 顾名思义&#xff0c;从理科生的角度来说&#xff0c;【优绩主义】以优秀的成绩作为评判人生是否成功的极大型指标&#xff0c;在东亚的【休息羞…

性能优化之自定义指令实现图片懒加载

1&#xff09;图片懒加载 是常见的用于在页面滚动时动态加载图片&#xff0c;而不是在页面加载时一次性加载所有图片。性能优化必备提高页面加载速度的手段&#xff0c;特别是在包含大量图片的网站上。 图片懒加载的原理&#xff0c;其实就是&#xff0c;当图片出现在视口内时…

数据分析:宏基因组的荟萃分析之MMUPHin

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 介绍 批次效应是实验中由于样本处理和测序技术变异引起的非生物学差异&#xff0c;可能干扰研究结果。这种效应难以完全消除&#xff0c;但可通过方法如PCA、PC…

【Vue3】Pinia getters

【Vue3】Pinia getters 背景简介开发环境开发步骤及源码 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子。本…

求职leetcode题目(6)

1.简化路径 解题思路: 根据题意&#xff0c;使用栈进行模拟即可。 具体的&#xff0c;从前往后处理 path&#xff0c;每次以 item 为单位进行处理&#xff08;有效的文件名&#xff09;&#xff0c;根据 item 为何值进行分情况讨论&#xff1a; item 为有效值 &#xff1a;存…

AQS框架

文章目录 概要AQS概述公平锁与非公平锁原理可重入 概要 假设现在需要写一个SDK层面的锁&#xff0c;应该如何实现呢&#xff1f; 初步的思路如下&#xff1a; 搞一个状态标记&#xff0c;用来表示持有或未持有锁&#xff0c;但得是 volatile 类型的保证线程可见性。编写一个 …

揭秘公司高效查快递的秘密武器

在快节奏的现代商务环境中&#xff0c;物流管理的效率直接关系到企业的运营成本和客户满意度。对于拥有大量快递业务往来的公司而言&#xff0c;如何快速、准确地追踪每一个包裹的物流信息&#xff0c;成为了一项至关重要的任务。今天&#xff0c;我们将揭秘一款公司高效查快递…

智慧农场数字港系统设计与实现

1 项目介绍 1.1 摘要 农业是一个国家的根本之一&#xff0c;也是国家经济、社会发展的重中之重&#xff0c;从“粮食第一”方针到农业生产市场化&#xff0c;再到乡村振兴、加强扶持农业技术创新和基础建设&#xff0c;我国的农业发展以及走过了几个阶段&#xff0c;并一直在…

Nature教你怎么用GPT做学术

ChatGPT如何助力学术写作&#xff1a;三个关键方式 生成性人工智能&#xff08;AI&#xff09;在近年来逐渐成为学术界的热门话题。Dritjon Gruda在2024年4月发表于《Nature》的一篇文章中&#xff0c;详细探讨了ChatGPT如何在学术写作、编辑和同行评审中提供帮助。这篇文章将…

第R2周:Pytorch实现:LSTM-火灾温度预测

nn.LSTM() 函数详解 nn.LSTM 是 PyTorch 中用于创建长短期记忆&#xff08;Long Short-Term Memory&#xff0c;LSTM&#xff09;模型的类。LSTM 是一种循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;的变体&#xff0c;用于处理序列数据&#…

常见的框架漏洞

框架 Web框架(Web framework)或者叫做Web应⽤框架(Web application framework)&#xff0c;是⽤于 进⾏Web开发的⼀套软件架构。⼤多数的Web框架提供了⼀套开发和部署⽹站的⽅式。为Web的 ⾏为提供了⼀套⽀持⽀持的⽅法。使⽤Web框架&#xff0c;很多的业务逻辑外的功能不需要⾃…