💪 图像算法工程师,专业从事且热爱图像处理,图像处理专栏更新如下👇:
📝《图像去噪》
📝《超分辨率重建》
📝《语义分割》
📝《风格迁移》
📝《目标检测》
📝《图像增强》
📝《模型优化》
📝《模型实战部署》
📝《图像配准融合》
📝《数据集》
📝《高效助手》
📝《C++》
目录
一、要求
实现一个通用的数组类,要求如下:
-
可以对内置数据类型以及自定义数据类型的数据进行存储;
-
将数组中的数据存储到堆区;
-
构造函数中可以传入数组的容量;
-
提供对应的拷贝构造函数以及operator=防止浅拷贝问题;
-
提供尾插法和尾删法对数组中的数据进行增加和删除;
-
可以通过下标的方式访问数组中的元素;
-
可以获取数组中当前元素个数和数组的容量;
二、实现
2.1 类模版的创建
创建一个MyArray.hpp文件和一个主函数main.cpp文件,见下:
类模版定义代码见下,写在MyArray.hpp文件中:
#pragma once
#include <iostream>
using namespace std;
template<class T>
class MyArray
{
private:
T* pAddress; // 指针指向堆区开辟的真实数据
int m_Capacity; // 数组容量
int m_Size; // 数组大小
};
2.2 构造函数
有参构造函数的定义见下,包含数组的容量、大小和地址,做初始化操作,代码见下:
// 有参构造 参数容量
MyArray(int capacity)
{
cout << "Myarray有参构造调用" << endl;
this->m_Capacity = capacity;
this->m_Size = 0;
this->pAddress = new T[this->m_Capacity];
}
2.3 拷贝构造函数
拷贝构造函数代码见下:
// 拷贝构造
MyArray(const MyArray& arr)
{
cout << "Myarray拷贝构造调用" << endl;
this->m_Capacity = arr.m_Capacity;
this->m_Size = arr.m_Size;
//this->PAddress = arr.pAddress; // 系统默认浅拷贝
// 深拷贝
this->pAddress = new T[arr.m_Capacity];
// 将arr中的数据都拷贝过来
for (int i = 0; i < this->m_Size; i++)
{
this->pAddress[i] = arr.pAddress[i];
}
}
2.4 深拷贝
对 = 操作符进行重载,防止浅拷贝问题,关于深拷贝和浅拷贝的理解,参考我另外一篇博文:C++中的深拷贝和浅拷贝通俗故事理解
深拷贝代码见下:
// 重载 = 操作符 防止浅拷贝问题
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];
}
return *this;
}
2.5 重载[ ]操作符
重载[ ]操作符是为了后面能够通过arr[i]访问数组中的元素,代码见下:
// 重载 [] 操作符 ,通过下标方式访问数组中的元素 arr[0]=100
T& operator[](int index) // 运算符重载
{
return this->pAddress[index];
}
2.6 尾插法
在数组尾端插入元素的代码见下:
// 尾插法
void Push_Back(const T& val)
{
// 判断容量是否等于大小
if (this->m_Capacity == this->m_Size)
{
return;
}
this->pAddress[this->m_Size] = val; // 在数组的尾端插入数据
this->m_Size++; // 更新数组大小
}
2.7 尾删法
在数组尾端删除元素的代码见下:
// 尾删法
void Pop_Back()
{
// 让用户访问不到最后一个元素,即为尾删,逻辑删除
if (this->m_Size == 0)
{
return;
}
this->m_Size--;
}
2.8 获取数组容量
获取数组容量代码见下:
// 返回数组容量
int getCapacity()
{
return this->m_Capacity;
}
2.9 获取数组长度
获取数组长度代码见下:
// 返回数组大小
int getSize()
{
return this->m_Size;
}
2.10 析构函数
在析构函数中,主要写在堆区创建内存数据释放,并将指针置为空,避免野指针,将数组容量和大小都置为0,代码见下:
// 析构函数
~MyArray()
{
if (this->pAddress != NULL)
{
cout << "Myarray析构函数的调用!" << endl;
delete[] this->pAddress; // 将堆区中的数据释放
this->pAddress = NULL;
this->m_Capacity = 0;
this->m_Size = 0;
}
}
2.11 完整代码
上面各个模块组合起来的完整代码见下,写在MyArray.hpp文件中:
// 自己通用的类数组
#pragma once
#include <iostream>
using namespace std;
template<class T>
class MyArray
{
public:
// 有参构造 参数容量
MyArray(int capacity)
{
cout << "Myarray有参构造调用" << endl;
this->m_Capacity = capacity;
this->m_Size = 0;
this->pAddress = new T[this->m_Capacity];
}
// 拷贝构造,为了防止浅拷贝的问题
MyArray(const MyArray& arr)
{
cout << "Myarray拷贝构造调用" << endl;
this->m_Capacity = arr.m_Capacity;
this->m_Size = arr.m_Size;
//this->PAddress = arr.pAddress; // 系统默认浅拷贝
// 深拷贝
this->pAddress = new T[arr.m_Capacity];
// 将arr中的数据都拷贝过来
for (int i = 0; i < this->m_Size; i++)
{
// 如果T为对象,而且还包含指针,必须需要重载=操作符,因为这个等号不是构造而是赋值。
// 普通类型可以直接=,但是指针类型需要深拷贝
this->pAddress[i] = arr.pAddress[i];
}
}
// 重载 = 操作符 防止浅拷贝问题
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];
}
return *this;
}
// 重载 [] 操作符 ,通过下标方式访问数组中的元素 arr[0]=100
T& operator[](int index) // 运算符重载
{
return this->pAddress[index];
}
// 尾插法
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--;
}
// 返回数组容量
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;
this->m_Capacity = 0;
this->m_Size = 0;
}
}
private:
T* pAddress; // 指针指向堆区开辟的真实数据
int m_Capacity; // 数组容量
int m_Size; // 数组大小
};
三、测试
3.1 内置数据类型测试
3.1.1 代码
内置数据类型测试代码见下,写在Array_class_encapsulation_main.cpp文件中:
#include<iostream>
using namespace std;
#include "MyArray.hpp"
#include<string>
// 打印数组中的元素
void printIntArray(MyArray<int>& arr)
{
for (int i = 0; i < arr.getSize(); i++)
{
cout << arr[i] << endl;
}
}
void test01()
{
MyArray<int>arr1(5);
//MyArray<int>arr2(arr1);
//MyArray<int>arr3(100); // 本来有100个数据,100的容量
//arr3 = arr1; // 做等号赋值的时候先把100清空,再把arr1中的数据做深拷贝操作
for (int i = 0; i < 5; i++)
{
// 利用尾插法向数组中插入数据
arr1.Push_Back(i);
}
cout << "arr1的打印输出为:" << endl;
printIntArray(arr1);
cout << "arr1的容量为:" << arr1.getCapacity() << endl;
cout << "arr1的大小为:" << arr1.getSize() << endl;
MyArray<int>arr2(arr1);
cout << "arr2的打印输出为:" << endl;
printIntArray(arr2);
// 尾删
arr2.Pop_Back();
cout << "arr2的容量为:" << arr2.getCapacity() << endl;
cout << "arr2的大小为:" << arr2.getSize() << endl;
}
int main()
{
test01();
//test02();
system("pause");
return 0;
}
3.1.2 输出
运行3.1.1中代码,输出见下:
3.2 自定义数据类型测试
3.2.1 代码
自定义数据类型测试代码见下,写在Array_class_encapsulation_main.cpp文件中:
#include<iostream>
using namespace std;
#include "MyArray.hpp"
#include<string>
// 测试自定义数据集
class Person
{
public:
Person() {}; // 默认构造
Person(string name, int age) // 有参构造
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void printPersonArray(MyArray<Person>& arr)
{
for (int i = 0; i < arr.getSize(); i++)
{
cout << "姓名:" << arr[i].m_Name <<"\t" << "年龄:" << arr[i].m_Age << endl;
}
}
void test02()
{
MyArray<Person> arr(10);
Person p1("李元芳", 18);
Person p2("公孙离", 20);
Person p3("虞姬", 28);
Person p4("狄仁杰", 40);
Person p5("孙尚香", 30);
// 将数据插入到数组中
arr.Push_Back(p1);
arr.Push_Back(p2);
arr.Push_Back(p3);
arr.Push_Back(p4);
arr.Push_Back(p5);
// 打印数组
printPersonArray(arr);
// 输出容量
cout << "arr的容量为:" << arr.getCapacity() << endl;
// 输出大小
cout << "arr的大小为:" << arr.getSize() << endl;
}
int main()
{
//test01();
test02();
system("pause");
return 0;
}
3.2.2 输出
运行3.2.1中代码,输出见下:
四、总结
以上就是C++中类模版案例,数组封装,希望能帮你理解。本人参考学习的是黑马程序员,仅作为笔记记录。
感谢您阅读到最后!😊总结不易,多多支持呀🌹 点赞👍收藏⭐评论✍️,您的三连是我持续更新的动力💖
关注下面「视觉研坊」,获取干货教程、实战案例、技术解答、行业资讯!