news 2026/4/18 9:44:58

Day17 C++提高 之 类模板案例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day17 C++提高 之 类模板案例

类模板案例

实现一个通用的数组类,要求如下:

  • 可以对内置数据类型以及自定义数据类型的数据进行存储;
  • 将数组中的数据存储到堆区(new);
  • 构造函数中可以传入数组的容量(有参构造);
  • 提供对应的拷贝构造函数以及operator = 防止浅拷贝问题;
  • 提供尾插法和尾删法对数组中的数据进行增加和删除;
  • 可以通过下标的方式访问数组中的元素;
  • 可以获取数组中当前元素个数和数组的容量(私有化,设置接口可以访问,但不可修改)

构建思路:

创建一个数组的类,类中需要有数组、数组的容量、数组当前元素个数;这个数组可以存储用户输入的数据类型的数据(数据类型包含系统内置以及用户自定义的数据类型),所以数组中的每一个元素的数据类型都是通用数据类型 T,将数据开放到堆区(用new,但new出来的一般都是指针,所以用T* =new T[n])。所以在数组类的内部维护的数组应该是T* pAddress,这个指针维护的是堆区真实存放数组元素的指针;数组的属性可以写为private,其他的写public的接口,接口应该有有参构造、拷贝构造(深拷贝)、operator、析构函数;如果是编译器提供的拷贝构造(浅拷贝)以及编译器提供的operator=都会出现浅拷贝的问题,所以需要自己写深拷贝解决这个问题(当数据有在堆区的数据,一定要自己写拷贝构造函数和operator函数防止浅拷贝问题;利用数组的下标访问数组中的元素?提供对外接口(尾插法、尾删法、获取数组容量、获取数组大小)。

因为不知道用户传入的类型是什么?所以每个数据的类型是T,模板化;用户传入容量,就new T[n]即可(这里n是用户传入的容量),返回的是T*;

类模板做分文件编写的时候,成员函数不好实现,所以将.h文件变为.hpp文件,将声明和实现都写在其中。

myArray.hpp文件

#pragma once #include<iostream> using namespace std; #include<string> //类模板作分文件编写,会报错,所以写在一个文件中,改后缀名为.hpp template<class T> class MyArray { //对外的成员函数 public: //有参构造,让用户输入容量,所以参数是用户传入的容量 MyArray(int capacity)//初始化属性值 { //cout << "myArray有参构造函数的调用" << endl; this->m_Capacity = capacity; this->m_Size = 0;//最开始容量为0 //pAddress指针指向在堆区开辟的空间 this->pAddress = new T[this->m_Capacity];//对数组进行初始化,开辟出用户需要的空间 } //拷贝构造:防止浅拷贝的问题,需要自己写拷贝构造函数 //类对象作为参数传入对象时调用拷贝构造函数 MyArray(const MyArray& arr) { //将arr数组中的值拷贝过来 //cout << "myArray拷贝构造函数的调用" << endl; this->m_Capacity = arr.m_Capacity; this->m_Size = arr.m_Size; //this->pAddress = arr.m_pAddress;浅拷贝的问题,指针不可以直接拷贝,会导致堆区的数据重复释放 //深拷贝 this->pAddress = new T[arr.m_Capacity];//开辟一样大小的空间 //将arr中的数据都拷贝过来 for (int i = 0; i < this->m_Size; i++) { this->pAddress[i] = arr.pAddress[i];//数组中的元素做一个传递 } } //operator=防止浅拷贝问题,进行重载,返回对象是本身,防止出现连等的操作 //两个对象直接=号时进行operator操作 //重载=。让两个对象可以直接赋值 MyArray& operator=(const MyArray &arr) { //cout << "myArray的operator=函数的调用" << endl; //先判断原来堆区是否有数据,如果有,先释放,再深拷贝 if (this->pAddress != NULL) { delete[] this->pAddress; this->pAddress = NULL; this->m_Capacity = 0; this->m_Size = 0; } //深拷贝 this->m_Capacity = arr.m_Capacity; this->m_Size - arr.m_Size; this->pAddress = new T[arr.m_Capacity];//先开辟一样大小的空间 for (int i = 0; i < this->m_Size; i++) { this->pAddress[i] = arr.pAddress[i];//将arr中的数据全部拿过来 } return *this;//返回自身 } //尾插法 void Push_Back(const T& value)//向数组中插入数据value { //先判断数组容量还够不够 if (this->m_Size == this->m_Capacity) { cout << "数组容量已满!塞不下了!!" << endl; return; } this->pAddress[this->m_Size] = value;//将传入的值插入数组中下标尾size的地方,也就是当前数组的最后一维(尾插) this->m_Size++;//更改数组大小+1 } //尾删法 void Pop_Back() { //让用户访问不到最后一个元素,(逻辑尾删) //数组数量-1,指针前移一个 //先判断有没有 if (this->m_Size == 0) { cout << "当前数组为空!" << endl; return; } this->m_Size--; } //通过下标方式访问元素, //若想要函数返回可以作为一个左值存在A[1]=7,因为想要作为左值,就是要改变这个值(这里是将A[1]重新赋值为7),所以用&,改变内部系统的值 //重载[],让用户可以直接通过下标访问元素 T& operator[](int index) { return this->pAddress[index];//返回的类型是T } //返回数组的容量 int getCapacity() { return this->m_Capacity; } //返回数组大小 int getSize() { return this->m_Size; } //析构函数 ~MyArray() { //析构函数需要做的是释放空间并置空指针 if (this->pAddress != NULL) { //cout << "myArray析构造函数的调用" << endl; delete[] this->pAddress;//释放空间,是一个数组,所以需要加[] this->pAddress = NULL;//将指针置空防止是一个野指针 } } //需要维护的几个私有的属性 private: T* pAddress;//指针指向堆区开辟的真实数组 int m_Capacity;//数组容量 int m_Size;//数组元素数量 };

源文件

#include<iostream> using namespace std; #include<string> #include"myArray.hpp" //打印数组函数 void myPrint(MyArray<int> &arr) { for (int i = 0; i < arr.getSize(); i++) { cout << arr[i] << endl; } } //创建自定义数据类型 class Person { public: Person() {}; Person(string name, int age) { this->m_Name = name; this->m_Age = age; } string m_Name; int m_Age; }; void test01() { //声明数组 MyArray<int>arr1(5);//对象创建会先调用构造函数,随即调用析构函数,5是传入的容量,指定类型是int for (int i = 0; i < 5; i++) { //利用尾插法向数组中插入数据 arr1.Push_Back(i); } cout << "arr1中的数据输出为:" << endl; myPrint(arr1); cout << "arr1的容量为:" << arr1.getCapacity()<<endl; cout << "arr1的大小为:" << arr1.getSize() << endl; //将arr1的值赋值给arr2,需要调用拷贝构造函数 MyArray<int>arr2(arr1);//拷贝构造函数,深拷贝,将对象作为参数传入另一个对象 cout << "arr2中的数据输出为:" << endl; myPrint(arr2); //尾删法 arr2.Pop_Back(); cout << "arr2的容量为:" << arr2.getCapacity() << endl; cout << "arr2的大小为:" << arr2.getSize() << endl; cout << "arr2中的数据输出为:" << endl; myPrint(arr2); MyArray<int>arr3(100);//创建arr3容量为100,调用有参构造函数 arr3 = arr1;//对arr3重新赋值,会调用operator的函数,赋值操作,先将arr3中的内容清空,再进行赋值拷贝操作 } void myPrintPerson(MyArray<Person>& arr) { for (int i = 0; i < arr.getSize(); i++) { cout << arr[i].m_Name << " "<< arr[i].m_Age << endl; } } //测试自定义类型 void test02() { MyArray<Person>arr(5); Person p1("懒羊羊", 10); Person p2("喜羊羊", 13); Person p3("沸羊羊", 13); Person p4("美羊羊", 12); Person p5("暖羊羊", 14); //将数据插入到数组中 arr.Push_Back(p1); arr.Push_Back(p2); arr.Push_Back(p3); arr.Push_Back(p4); arr.Push_Back(p5); //打印数组 myPrintPerson(arr); cout << "arr的容量为:" << arr.getCapacity() << endl; cout << "arr的大小为:" << arr.getSize() << endl; //尾删法 arr.Pop_Back(); cout << "arr中的数据输出为:" << endl; myPrintPerson(arr); cout << "arr的容量为:" << arr.getCapacity() << endl; cout << "arr的大小为:" << arr.getSize() << endl; } int main() { test01(); test02(); system("pause"); return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 5:25:52

【PYTHON-YOLOV8N】如何自定义数据集

【PYTHON-YOLOV8N】如何自定义数据集一、核心前提&#xff1a;明确 YOLO 数据集格式二、步骤 1&#xff1a;整理原始数据&#xff08;图片&#xff09;1. 文件夹结构&#xff08;推荐&#xff09;2. 数据收集/筛选三、步骤 2&#xff1a;标注数据&#xff08;生成 YOLO 格式标签…

作者头像 李华
网站建设 2026/4/17 1:36:11

1小时快速搭建:基于Guava的实时数据监控原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个实时数据监控看板原型&#xff0c;使用Guava实现&#xff1a;1) 多源数据收集器&#xff0c;2) 滑动时间窗口统计&#xff0c;3) 异常值检测&#xff0c;4) 实时可视化图表…

作者头像 李华
网站建设 2026/4/18 9:34:26

Spring开发效率对比:传统vs快马AI代码生成

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 请生成两个对比项目&#xff1a;1.传统手动开发的Spring Boot用户管理系统 2.使用AI生成的相同功能系统。要求两个项目都包含&#xff1a;用户注册登录、权限管理、数据校验、日志记…

作者头像 李华
网站建设 2026/4/18 8:45:51

AI如何帮你快速生成Vue二维码组件?

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 请生成一个基于Vue 3的二维码生成组件&#xff0c;要求&#xff1a;1. 使用vue-qrcode库作为基础 2. 包含可配置的二维码大小、颜色和容错级别 3. 提供实时预览功能 4. 支持点击下载…

作者头像 李华
网站建设 2026/4/18 8:44:29

Diffusion Transformer实战:构建艺术创作助手

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 在快马平台上开发一个艺术创作助手应用&#xff0c;基于Diffusion Transformer技术。具体要求&#xff1a;1. 用户可上传草图作为生成基础&#xff1b;2. 提供风格转换功能&#xf…

作者头像 李华
网站建设 2026/4/13 21:31:40

深度学习基础术语介绍:标量和向量

本文博主将通俗地解释一下标量和向量。它们是构建张量世界乃至整个数学和物理世界最基础的“乐高积木”。1. 标量 —— “单一的量” 一句话概括&#xff1a;标量就是一个只有大小&#xff0c;没有方向的“单个数字”。它是什么&#xff1f; 标量是零维张量。它没有长度、宽度、…

作者头像 李华