使用C++类模板实现自定义数组
案例描述
C++泛型编程的一种主要技术是使用模板(templates)。模板允许程序员编写通用的代码,以处理各种数据类型,而不仅仅是特定的数据类型。通过使用模板,可以实现代码的重用性和灵活性,使得在不同类型上编写相似的代码变得更加容易。
因此,本案例旨在利用类模板实现一个通用的数组,可以对内置数据类型或自定义数据类型进行存储。
案例需求
- 定义数组类,实现对任意类型数据存储 —— 定义类模板;
- 将数组中的数据存储到堆区 —— 利用new开辟堆区内存;
- 构造函数中可以传入数组的容量 —— 数组类中包括成员变量”容量“,且实现输入容量的构造函数;
- 提供对应的拷贝构造函数以及operator=防止浅拷贝问题 —— 实现拷贝构造函数,重载= 运算符,使用new执行深拷贝
- 提供尾插法和尾删法对数组中的数据进行增删 —— 实现对应成员函数
- 可以通过下标的方式访问数组中的元素 —— 重载[] 运算符
- 可以获取数组中当前元素个数和数组的容量 —— 实现对应成员变量
// 根据上述需求,可以大致确定类模板中的内容
类模板{
public:
构造函数
拷贝构造函数
重载operator=
重载[]
尾插函数
尾删函数
获得数组容量
获得元素个数
析构函数
private:
指针
数组容量
元素个数
}
代码实现
对于类模板,由于成员函数在调用阶段才会被创建,因此其无法正常进行分文件编写。于是,我们将数组类MyArray
定义在*.hpp*文件中。
MyArray.hpp
#ifndef MYARRAY_HPP_INCLUDED // 或者使用 #pragma once 保护头文件
#define MYARRAY_HPP_INCLUDED
#include <iostream>
using namespace std;
#endif // MYARRAY_HPP_INCLUDED
template <class T> // 声明模板
class MyArray{
public:
// 构造函数
MyArray(int capacity){
this->m_capacity = capacity;
this->m_size = 0;
this->mAddress = new T[capacity]; // 在堆区新开辟数组
}
// 拷贝构造函数
MyArray(const MyArray & arr){
this->m_capacity = arr.m_capacity;
this->m_size = arr.m_size;
this->mAddress = new T[this->m_capacity]; // 要先定义
for (int i=0;i<arr.m_size;i++){
this->mAddress[i] = arr.mAddress[i]; // 这里需要调用类型T中的赋值操作,如果类型T是自定义类型,要注意在该类中潜在存在的浅拷贝问题
}
}
MyArray& operator =(const MyArray & arr){
// 先判断原来堆区是否有问题
if (this->mAdress != nullptr){
delete[] this->mAddress; // 使用new[]开辟的,需要用delete[]删除
this->m_size = 0;
this->m_capacity = 0;
}
// 赋值
this->m_capacity = arr.m_capacity;
this->m_size = arr.m_size;
// 深拷贝
this->mAddress = new T[this->m_capacity];
for (int i=0;i<this->m_size;i++){
this->mAddress[i] = arr.mAddress[i];
}
// 注意要有返回值
return *this; // 解引用,获得this指向的对象,也就是MyArray类的对象
}
// 重写 []
T& operator [](int index){
return this->mAddress[index]; // 未考虑越界问题
}
// 尾插函数
void m_push_back(const T & val){
// 首先判断当前数组是否饱和
if (this->m_size < this->m_capacity){
this->mAddress[this->m_size] = val;
this->m_size++;
}
}
// 尾删函数
void m_pop_back(){
// 直接修改当前元素个数即可
if (this->m_size > 0){
this->m_size--;
}
}
// 获得容量
int getCapacity(){
return this->m_capacity;
}
// 获得元素个数
int getSize(){
return this->m_size;
}
// 析构函数
~MyArray() {
if (this->mAddress != NULL){
delete[] this->mAddress;
this->m_capacity = 0;
this->m_size = 0;
this->mAddress = NULL;
}
}
private:
T * mAddress; // 指向堆区数组的指针
int m_capacity; // 数组容量
int m_size; // 数组元素个数
};