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

案例:自定义数组类
需求:
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.rhkb.cn/news/394460.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot + Vue的宿舍管理系统

前言 文末获取源码数据库 感兴趣的可以先收藏起来&#xff0c;需要学编程的可以给我留言咨询&#xff0c;希望帮助更多的人 精彩专栏推荐订阅 不然下次找不到哟 Java精品毕设原创实战项目 作者的B站地址&#xff1a;程序员云翼的个人空间-程序员云翼个人主页-哔哩哔哩视频 csd…

vue3+axios请求导出excel文件

在Vue 3中使用axios请求导出Excel文件&#xff0c;可以发送一个GET或POST请求&#xff0c;并设置响应类型为blob或arraybuffer&#xff0c;然后使用new Blob()构造函数创建一个二进制文件&#xff0c;最后使用URL.createObjectURL()生成一个可以下载的链接。 先看代码 import…

Stable Diffusion绘画 | 必备插件安装推荐

新手必备安装的插件推荐如下&#xff1a; 汉化语言包&#xff1a;汉化插件GitHub地址&#xff1b;双语对照插件GitHub地址无边图库&#xff1a;无边图库插件GitHub地址ControlNet&#xff1a;已默认安装 插件安装 最推荐的安装方式&#xff1a;通过「可下载」、「从网址安装…

Qt Modbus 寄存器读写实例

一.线圈状态寄存器读写 项目效果如下 1. 写单个寄存器 MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status); int addrui->spinBoxwirte_addr->value();int dataui->spinBoxwirte_data->value();int ret modbus_write_bit(mb,addr,d…

学习c#-4语句 ,条件,循环

代码&#xff1a; string name "小赵"; //条件判断 if (name "小赵") { Console.WriteLine("我是小赵"); } else { Console.WriteLine("我不是小赵"); } // switch条件判断 switch (name) { case "小…

5.3 匿名函数:Python编程中的隐士大师

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; 工&#x1f497;重&#x1f497;hao&#x1f497;&#xff1a;野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

嵌入式初学-C语言-十七

#接嵌入式初学-C语言-十六# 函数的递归调用 含义&#xff1a; 在一个函数中直接或者间接调用了函数本身&#xff0c;称之为函数的递归调用 // 直接调用a()->a(); // 间接调用a()->b()->a();a()->b()->..->a();递归调用的本质&#xff1a; 本是是一种循环…

【QT】Qt 音视频

Qt 音视频 Qt 音视频1. Qt 音频2. Qt 视频 Qt 音视频 在 Qt 中&#xff0c;音频主要是通过 QSound 类来实现。但是需要注意的是 QSound 类只支持播放 wav 格式的音频文件。也就是说如果想要添加音频效果&#xff0c;那么首先需要将非 wav 格式的音频文件转换为 wav 格式。 通…

JavaWeb之servlet关于Ajax实现前后端分离

一、什么是Ajax: AJAX Asynchronous JavaScript and XML&#xff08;异步的 JavaScript 和 XML&#xff09;。 AJAX 不是新的编程语言&#xff0c;而是一种使用现有标准的新方法。 AJAX 最大的优点是在不重新加载整个页面的情况下&#xff0c;可以与服务器交换数据并更新部…

Nuxt2:强制删除window.__NUXT__中的数据

一、问题描述 在以前的一篇文章《Nuxt3: 强制删除__NUXT_DATA__的一种方式》中曾介绍了在Nuxt3中如何删除存在于页面id为__NUXT_DATA__的script节点中的数据。 此次&#xff0c;Nuxt2与Nuxt3不同在于它的数据是存在于window.__NUXT__&#xff0c;那么该如何处理呢&#xff1f;…

2025深圳国际户外庭院营地用品博览会

2025深圳国际户外庭院营地用品博览会 2025 Shenzhen International Outdoor Courtyard Camping Supplies Expo 时间&#xff1a;2025年02月27-3月01日 地点&#xff1a;深圳会展中心&#xff08;福田馆&#xff09; 详询主办方陆先生 I38&#xff08;前三位&#xff09; …

如何用OceanBase与DataWorks,打造一站式的数据集成、开发和数据服务

导语&#xff1a;在OceanBase 2024年开发者大会的技术生态论坛上&#xff0c;阿里云DataWorks团队的高级技术专家罗海伟&#xff0c;详细阐述了一站式大数据开发治理平台DataWorks的能力&#xff0c;并对于如何基于OceanBase和Dataworks构建一站式数据集成、开发以及数据服务进…

Linux驱动开发—Linux内核定时器概念和使用详解,实现基于定时器的字符驱动

文章目录 内核定时器概念在Linux驱动模块中使用定时器软定时器&#xff08;Soft Timers&#xff09;jiffies 含义高精度定时器&#xff08;High Resolution Timers&#xff09; 实现倒计时字符设备驱动 内核定时器概念 在 Linux 内核中&#xff0c;定时器是用来管理和调度延迟…

8.7-主从数据库的配置+mysql的增删改查

一、mysql环境的配置 1.环境准备 &#xff08;1&#xff09;主数据库 #关闭防火墙 [rootmaster ~]# systemctl stop firewalld#关闭selinux [rootmaster ~]# setenforce 0#下载lrzsz工具 [rootmaster ~]# yum -y install lrzsz#安装rsync [rootmaster ~]# yum -y install rs…

低代码平台:效率利器还是质量妥协?

目录 低代码平台&#xff1a;效率利器还是质量妥协&#xff1f; 一、引言 二、低代码平台的定义和背景 1、什么是低代码平台&#xff1f; 2、低代码平台的兴起 三、低代码开发的机遇 1、提高开发效率 2、降低开发成本 3、赋能业务人员 四、低代码开发的挑战 1、质量…

pgbackrest备份方案(差异和增量备份的区别)

pgbackrest备份方案(差异和增量备份的区别) 一 备份 全量备份&#xff1a; 将数据库集群的全部内容复制到备份中。数据库集群的第一个备份始终是全量备份。始终能够直接还原全量备份。全量备份不依赖于完整备份之外的任何文件来保持一致性。 差异备份&#xff1a; 仅复制自…

3D展示的前景如何?

随着人类科技的不断进步&#xff0c;对未来的趋势也肯定是向高纬度发展。3D取代2D只是一个所需时间长短而已&#xff0c;题主既然这么问&#xff0c;说明肯定是意识到了3D是未来的趋势&#xff0c;那么就应该多接触和了解未来的3D平台及应用工具、应用领域等。 之前2G\3G时代&…

1.MongoDB入门指南之开篇

1. 写在前面 MongoDB大家可能听说过&#xff0c;但是要怎么学习&#xff1f;先学习哪个&#xff0c;很多人是不知道的&#xff0c;毕竟面对一个未知的事物&#xff0c;迷茫是很多人都会遇到的&#xff0c;从今天起我们就开始系统的介绍MongoDB的学习。 2. 课程介绍 课程主要分…

【Android Studio】原生应用部署第三方插件(探针)

一、本地引入包流程 &#xff08;一&#xff09;本地引入包内容 &#xff08;二&#xff09;本地引入包操作步骤 将 【probe-android-sdk】目录里面所有的aar包复制到嵌码项目工程&#xff08;App级别&#xff09;的 libs 目录下 二、添加插件 &#xff08;一&#xff09;…

Qt文件读写

Qt中文件读写类简述 包含头文件#include <QFile> 读写模式如下 枚举 文件读写步骤 1 先使用string 类型来接受打开文件的返回值 QFileDialog::getOpenFileName(this,"文件","./"); //打开一个文件 2 构建文件对象 Qfile ff (qstring)接受打…