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

  • 可以对内置数据类型以及自定义数据类型的数据进行存储。

  • 将数组中的数据存储到堆区

  • 构造函数中可以传入数组的容量

  • 提供对应的拷贝构造函数以及operator=防止浅拷贝问题

  • 提供尾插法尾删法对数组中的数据进行增加和删除

  • 可以通过下标的方式访问数组中的元素

  • 可以获取数组中当前元素个数数组的容量



需求分析:

一、类的基本结构:

设计一个MyArray的类,类内属性为:

  • 类内维护一个数组:T* item = new T[5];
  • 维护表示一个关于数组容量的属性:m_Capacity。
  • 维护表示一个数组元素个数的属性:m_Size。

属性写为private权限。

二、数据结构:

维护的这个数组要开辟到堆区。在堆区中维护的这个数据类型必须是通用的,即泛型的,支持多样性。所以堆中数组元素类型为T。

为此:数组中每个元素为 T* item = new T[5];

三、接口功能:

对外要提供一些功能函数接口:public:

  • 构造函数(传入容量):传入参数,指定数组的容量。
  • 拷贝构造:
  • operator=:运算符重载。类内存在堆区的数据,为了防止 浅拷贝重复释放 的问题。
  • 利用下标的方式:访问数组元素
  • 尾插法:
  • 尾删法:
  • 获取数组的容量
  • 获取数组的元素个数。
  • 析构函数:


四:一步步实施:

这个需要内容比较多,不适合写在一个文件里面,所以分文件写:类模板分文件的编写,最好将声明和实现写在一起:都放在.hpp文件中。

先写一个类模板的文件:MyArray.hpp文件。

#include<iostream>
using namespace std;template<typename T>
class MyArray
{
public:// 初始化:有参构造 参数 容量MyArray(int capacity){this->m_Capacity = capacity;this->m_Size = 0;this->pAddress = new T[this->m_Capacity];// 测试代码:cout << "MyArray 有参构造 被调用。" << endl;}// 拷贝构造MyArray(const MyArray& arr){this->m_Capacity = arr.m_Capacity;this->m_Size = arr.m_Size;//this->pAddress  // 开辟在堆区,所以需要深拷贝,从堆中,重新开辟一块空间,拷贝过去。this->pAddress = new T[arr.m_Capacity];// 将arr中的数据都拷贝过来。for (int i = 0; i < this->m_Size; i++){this->pAddress[i] = arr.pAddress[i];}cout << "MyArray 拷贝构造 被调用。" << endl;}// operator= 防止浅拷贝问题。MyArray& operator=(const MyArray& arr){// 先判断原来堆区是否有数据。如果有先释放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 < arr.m_Capacity; i++){this->pAddress[i] = arr.pAddress[i];}cout << "MyArray 运算符重载operator= 被调用。" << endl;return *this;   // 返回自身。}// 析构函数:~MyArray(){if (this->pAddress!=NULL){delete[] this->pAddress;this->pAddress = NULL;    // 置空,防止称为野指针。cout << "MyArray 析构函数 被调用。" << endl;}}private:T* pAddress;    // 指针指向堆区开辟的真实的数组。int m_Capacity; // 数组的容量int m_Size;     // 数组的大小
};

先把基本框架写出来,然后做个测试:在程序中写一个测试案例。补充打印测试。

先包含头文件:#include "MyArray.hpp"

void test01()
{int len = 5;MyArray<int> arr(len);MyArray<int> arr1(arr);  // 拷贝构造方式。MyArray<int> arr2(10);arr2 = arr;              // 运算符重载。}

阶段性测试:已经完成前面几个任务,只剩下最后三个任务:

先写:尾插法、尾删法

// 尾插法
void Push_Back(const T& val)
{// 插入之前先判断容量是否等于大小。if (this->m_Capacity == this->m_Size){return;}this->pAddress[this->m_Size] = val;   // 在数组末尾插入数据。this->m_Size++; // 更新数组大小。
}// 尾删法
void Pop_Back()
{// 让用户访问不到最后一个元素。即为尾删,逻辑删除。if (this->m_Size == 0){return;}this->m_Size--;
}

下标访问:

// 下标访问元素:返回类型为元素类型T,如果需要将返回值作为左值存在,那么需要返回引用。
T& operatoar[](int index)
{return this->pAddress[index];
}

返回数组容量、大小

// 返回数组容量
int getCapacity()
{return this->m_Capacity;
}// 返回数组大小
int getSize()
{return this->m_Size;
}

为了打印输出,我写了个友元来显示每一项:

friend void printArray(const MyArray<T>& arr)
{for (int i = 0; i < arr.m_Size; i++){cout << arr.pAddress[i] << " ";}cout << endl;
}
void test01()
{int len = 5;MyArray<int> arr(len);MyArray<int> arr1(arr);  // 拷贝构造方式。MyArray<int> arr2(10);arr2 = arr;              // 运算符重载。}void test02()
{int len = 5;MyArray<int> arr(len);for (int i = 0; i < len; i++){arr.Push_Back(i + 1);}cout << "初始化arr:";printIntArray(arr);  // 友元;// 测试尾删法:arr.Pop_Back();cout << "测尾删arr:";printIntArray(arr);  // 友元;// 测试尾插法;arr.Push_Back(99);printIntArray(arr);  // 友元;cout << arr.getCapacity() << endl;cout << arr.getSize() << endl;}


以上是关于内置数据类型的案例。来看看自定义类型案例。

#pragma once
#include<iostream>
using namespace std;template<typename T1, typename T2>
class Person
{
public:Person() {};    // 不加这个默认构造函数,会报错。Person(T1 name, T2 age);void showPerson();
private:T1 m_Name;T2 m_Age;
};// 类外实现
template<typename T1, typename T2>
Person<T1, T2>::Person(T1 name, T2 age)
{this->m_Name = name;this->m_Age = age;
}
template<typename T1, typename T2>
void Person<T1, T2>::showPerson()
{cout << "姓名:" << this->m_Name << ", 年龄:" << this->m_Age << endl;
}

我们直接套用前面几节中关于Person.hpp的类模板。然后来测试。

void printPersonArray(MyArray<Person<string, int>>& arr)
{for (int i = 0; i < arr.getSize(); i++){arr[i].showPerson();}
}// 看看自定义类数组效果
void test03()
{Person<string, int> p1("张三", 18);Person<string, int> p2("李四", 14);Person<string, int> p3("王五", 15);Person<string, int> p4("赵六", 16);Person<string, int> p5("田七", 17);MyArray<Person<string, int>> arr(5);  arr.Push_Back(p1);arr.Push_Back(p2);arr.Push_Back(p3);arr.Push_Back(p4);arr.Push_Back(p5);printPersonArray(arr);}

报错了;

没有合适的默认构造函数可用。因此需要在Person.hpp中,将默认构造函数,加进去,即:Person(){}。否则会报上面的错误。

类模板中引用其他类模板,被引用类模板要加上默认构造函数

此外两个深拷贝存在这样一个问题:待我技术成长了再来解决。

 

C++模板笔记十:类模板案例:通用数组类相关推荐

  1. 第十二周项目三-数组类运算的实现

    /**Copyright(c)2016,烟台大学计算机与控制工程学院*All rights reserved*文件名称:123.cpp*作 者:王蕊*完成日期:2016年5月24日*版 本 号:v1. ...

  2. 1分钟理清楚C++类模板和模板类区别

    目录 1.定义区别 2.程序举例 1.定义区别 类模板和模板类主要关注点是后一个单词. 类模板:主要描述的是模板,这个模板是类的模板.可以理解为一个通用的类,这个类中的数据成员,成员函数的形参类型以及 ...

  3. axure可视化大屏模板200例 •axure模板 大屏可视化 •axure数据可视化原型 •axure可视化组件 •axure

    可视化axure原型可视化大屏模板200例,带动画效果,可直接复用 axure可视化大屏模板200例 axure可视化大屏模板200例数据可视化原型可视化组件下载-无极低码 axure模板 大屏可视化 ...

  4. C++多态案例一计算器类

    C++多态案例一计算器类 多态案例一计算器类 案例描述 多态的优点 示例 多态案例一计算器类 案例描述 分别利用普通写法和多态技术,设计实现两个操作数进行运算的计算器类 多态的优点 代码组织结构清晰 ...

  5. 反射、Lambda表达式(Java学习笔记十二)

    文章目录 反射 Class 类 创建运行时类的对象 获取运行时类的完整结构 调用运行时类的指定结构 调用指定方法 调用指定属性 关于setAccessible方法的使用: 动态代理 Lambda表达式 ...

  6. 【数据结构与算法-java实现】三 Java数组类实现

    上一篇文章学习了:最好.最坏.平均.均摊时间复杂度的计算与分析方法. 本片文章学习数组这种结构.由于数组这种结构比较简单,本文直接简单介绍,然后给出两种实现数组类的Java代码:整形数组类与通用性的数 ...

  7. 无法创建t的通用数组_创建通用数组的问题

    无法创建t的通用数组 在这篇文章中,我们将介绍一篇全面的文章,其中介绍了创建通用数组的问题. Java编程语言于2004年9月在Java 5.0" Tiger"发行版中添加了泛型. ...

  8. 笔记②:牛客校招冲刺集训营---C++工程师(面向对象(友元、运算符重载、继承、多态) -- 内存管理 -- 名称空间、模板(类模板/函数模板) -- STL)

    0618 C++工程师 第5章 高频考点与真题精讲 5.1 指针 & 5.2 函数 5.3 面向对象(和5.4.5.5共三次直播课) 5.3.1 - 5.3.11 5.3.12-14 友元 友 ...

  9. 【Visual C++】游戏开发笔记四十六 浅墨DirectX教程十四 模板测试与镜面特效专场

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处.   文章链接: http://blog.csdn.net/zhmxy555/article/details/8632184 作者:毛星云( ...

最新文章

  1. 性能测试回归测试_自动网站性能回归测试
  2. 操作系统 作业调度实验报告
  3. list 是什么意思 php,php中list的功能是什么
  4. 试验ConcurrentHashmap
  5. 亲密关系-【沟通提示】-如何把学习到的东西用到生活中
  6. Linux Namespace机制简介
  7. javascript 使用canvas绘画
  8. 8.configurable product
  9. 黑马程序员 re模块的高级用法 学习笔记
  10. Kindle刷安卓双系统的方法
  11. QQ音乐.qmc3文件转换成正常mp3文件
  12. 关于Excel2003行数(65535)和列数(255)限制问题解决
  13. java中eof错误是啥意思_EOFException异常详解
  14. 京东API item_search - 按关键字搜索商品
  15. 短链接服务架构设计概览
  16. 2023springboot计算机毕业设计选题推荐、springboot计算机毕业设计题目大全
  17. linux服务器监控
  18. 数字信号处理与高频电路基础知识与实训QY-MS300E
  19. dmp如何导入mysql_oracle如何导入dmp
  20. 2021年9月PMP认证考试招生火热进行中!

热门文章

  1. “企业中台”与微服务架构
  2. 【linux】循序渐进学运维-find
  3. Mega16_CN3083 and NOKIA_5110实现太阳嫩充电器
  4. EBS R12 克隆详细步骤
  5. VS2019 community版本下载Extension太慢解决方案
  6. 关于微信名称特殊字符存数据库出问题; Incorrect string value: ‘\xF0\x9F\x90\xAF’ for column ‘nickName’ at row 1
  7. PS李涛老师的课程笔记 【PS初级】光和色的关系
  8. it团队建设方案参考
  9. 教育OA如何选型?教育OA系统选型必看技巧
  10. 思华科技助力盛大游戏构建全能型混合游戏云