【035】C++泛型编程(模板)实践:设计数组类模板模仿vector容器

C++泛型编程(模板)实践

  • 引言
  • 一、类模板的概述
  • 二、实现数组类模板
  • 三、类模板的继承
    • 3.1、类模板派生出普通类
    • 3.2、类模板派生出类模板
  • 总结

引言


💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。
👉
🎖️ CSDN实力新星,社区专家博主
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【034】C++泛型编程(模板)之 类模板详解(最全讲解)

一、类模板的概述

C++ 类模板是一种用于创建通用类的机制,它可以让程序员编写一次类,然后让它适用于多种类型,在实际编程中非常实用。

类模板和函数模板的定义和使用类似。有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同,类模板用于实现类所需数据的类型参数化。

类模板的定义方式类似于普通类的定义,只是需要在类名后面添加一对尖括号,其中包含类型参数列表。

设计一个数组类模板,可以存放任意数据类型。

二、实现数组类模板

类模板一般在hpp文件里面实现。由于数组类模板要存放任何数据类型,所以先定义一个模板类型T。
Data.hpp

#pragma once
#ifndef _DATA_H_
#include <string.h>
#include <iostream>
using namespace std;// 类模板
template <class T>
class MyArray {template<class T1>friend ostream& operator<<(ostream &out, MyArray<T1> ob);
private:T *arr;//数组首地址int size;//实际大小int capacity;//总容量大小。
public:MyArray();MyArray(int capacity);MyArray(const MyArray &ob);~MyArray();MyArray& operator=(MyArray &ob);void pushBack(T elem);//插入元素void sortArrary();//排序};#endif // !_DATA_H_template<class T>
MyArray<T>::MyArray()
{capacity = 5;size = 0;arr = new T[capacity];memset(arr, 0, sizeof(T)*capacity);
}template<class T>
MyArray<T>::MyArray(int capacity)
{this->capacity = capacity;size = 0;arr = new T[capacity];memset(arr, 0, sizeof(T)*capacity);
}template<class T>
MyArray<T>::MyArray(const MyArray & ob)
{this->capacity = ob.capacity;this->size = ob.size;this->arr = new T[this->capacity];memset(this->arr, 0, sizeof(T)*this->capacity);memcpy(this->arr, ob.arr, sizeof(T)*this->capacity);
}template<class T>
MyArray<T>::~MyArray()
{if (arr != NULL){delete[] arr;arr = NULL;}
}template<class T>
MyArray<T> & MyArray<T>::operator=(MyArray<T> & ob)
{// 判断 this->arr是否存在空间if (arr != NULL){delete[] arr;arr = NULL;}// TODO: 在此处插入 return 语句this->capacity = ob.capacity;this->size = ob.size;this->arr = new T[this->capacity];memset(this->arr, 0, sizeof(T)*this->capacity);memcpy(this->arr, ob.arr, sizeof(T)*this->capacity);return *this;
}template<class T>
void MyArray<T>::pushBack(T elem)
{// 判断容器是否满if (size == capacity){// 扩容capacity = 2 * capacity;// 申请临时空间T *tmp = new T[capacity];if (arr != NULL){// 将旧空间数据拷贝到新空间memcpy(tmp, arr, sizeof(T)*size);// 释放旧空间delete[] arr;}// arr指向新空间arr = tmp;}arr[size] = elem;size++;
}template<class T>
void MyArray<T>::sortArrary()
{if (size == 0){cout << "容器没有数据" << endl;return;}// 冒泡排序for (int i = 0; i < size - 1; i++){for (int j = 0; j < size - i - 1; j++){if (arr[j] > arr[j + 1]){T tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}template<class T1>
ostream& operator<<(ostream &out, MyArray<T1> ob)
{for (int i = 0; i < ob.size; i++){out << ob.arr[i] << " ";}out << endl;return out;
}

main.cpp

#include <iostream>
#include <string>
using namespace std;class Person {// 重载<<运算符friend ostream& operator<<(ostream &out, Person ob);
private:int num;string name;float score;
public:// 必须要有无参构造Person(){}Person(int num, string name, float score){this->num = num;this->name = name;this->score = score;}// 重载>运算符才能正确比较bool operator>(Person &ob){return num > ob.num;}
};ostream& operator<<(ostream &out,Person ob)
{out << ob.num << " " << ob.name << " " << ob.score << endl;return out;
}#include "Data.hpp"
int main()
{// 类模板实例化对象MyArray<int> arr01;arr01.pushBack(20);arr01.pushBack(60);arr01.pushBack(40);cout << arr01 << endl;arr01.sortArrary();cout << arr01 << endl;MyArray<char> arr02;arr02.pushBack('A');arr02.pushBack('H');arr02.pushBack('D');cout << arr02 << endl;arr02.sortArrary();cout << arr02 << endl;// 对象的存储MyArray<Person> person;person.pushBack(Person(102,"hello",92.30f));person.pushBack(Person(108, "world", 95.30f));person.pushBack(Person(103, "lests", 98.30f));person.sortArrary();cout << person << endl;return 0;
}

三、类模板的继承

3.1、类模板派生出普通类

在类模板派生处具体化为普通类。

示例:

#include <iostream>
using namespace std;template<class T1,class T2>
class Base {
private:T1 a;T2 b;
public:Base() {}Base(T1 a, T2 b);void showData();
};template<class T1, class T2>
Base<T1, T2>::Base(T1 a, T2 b)
{this->a = a;this->b = b;
}template<class T1, class T2>
void Base<T1, T2>::showData()
{cout << a << " " << b << endl;
}// 在类模板派生处具体化为普通类
class Son :public Base<int, char> {
public:int c;
public:Son(int a, char b, int c) :Base<int, char>(a, b) {this->c = c;}
};int main()
{Son ob(100, 'A', 200);ob.showData();return 0;
}

3.2、类模板派生出类模板

抽象化类型。

示例:

#include <iostream>
using namespace std;template<class T1,class T2>
class Base {
private:T1 a;T2 b;
public:Base() {}Base(T1 a, T2 b);void showData();
};template<class T1, class T2>
Base<T1, T2>::Base(T1 a, T2 b)
{this->a = a;this->b = b;
}template<class T1, class T2>
void Base<T1, T2>::showData()
{cout << a << " " << b << endl;
}// 在类模板派生类模板
template<class T1, class T2class T3>
class Son :public Base<T1, T2> {
public:T3 c;
public:Son(T1 a, T2 b, T3 c) :Base<T1, T2>(a, b) {this->c = c;}
};int main()
{Son ob(100, 'A', 200);ob.showData();return 0;
}

总结

C++ 的标准库中提供了 std::vector 容器,它是一个动态数组,能够在运行时根据需要动态调整大小。如果想要实现一个类似于 std::vector 的容器,需要考虑以下几个要点:

  1. 动态内存管理:类似于 std::vector,你需要使用动态内存分配来管理存储元素的内存。可以使用 newdelete 或者 mallocfree 等来实现。

  2. 大小和容量管理:你的容器应该具有类似于 std::vectorsize()capacity() 方法,用于获取当前存储元素的数量和容器的容量。当容量不足时,需要进行内存重新分配来扩大容量。

  3. 元素访问和操作:你的容器应该提供类似于 std::vectorpush_back()pop_back()at()front()back() 等方法来访问和操作容器中的元素。还需要实现类似于 std::vector 的迭代器来遍历容器。

  4. 内存管理和异常安全:你需要确保容器在内存管理和异常安全方面与 std::vector 一致。例如,在内存重新分配时,需要正确地处理内存释放和重新分配,以及在发生异常时确保容器的状态不会被破坏。

  5. 复制和移动语义:你的容器应该具有正确的复制和移动语义,包括拷贝构造函数、拷贝赋值运算符、移动构造函数和移动赋值运算符等。

  6. 内存回收:当容器不再需要时,需要正确地释放内存,避免内存泄漏。可以在容器的析构函数中进行内存释放。

总结起来,实现一个类似于 std::vector 的容器需要考虑动态内存管理、大小和容量管理、元素访问和操作、内存管理和异常安全、复制和移动语义以及内存回收等方面。这涉及到动态内存分配、指针和引用、构造函数和析构函数、运算符重载等 C++ 的一些基本概念和技术。在实际编程中,可以参考 std::vector 的实现和相关的 C++ 标准库文档来更深入地了解和实现类似的容器。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/8168.html

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

相关文章

常州工学院单片机及应用系统设计2021-2022 学年第 二 学期 考试类型 开卷 课程编码 0302005

第一题 #include "SC95F861x_C.H" #include <INTRINS.H> unsigned char keydata0; void delay(unsigned int timer) //延时函数 { while(timer>0) timer--; } void IOinit() { P5CON0x00; P5PH0x03; P3CON0xFF; P3PH0xFF; } void readke…

回归预测 | MATLAB实现PSO-DNN粒子群算法优化深度神经网络的数据多输入单输出回归预测

回归预测 | MATLAB实现PSO-DNN粒子群算法优化深度神经网络的数据多输入单输出回归预测 目录 回归预测 | MATLAB实现PSO-DNN粒子群算法优化深度神经网络的数据多输入单输出回归预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 回归预测 | MATLAB实现PSO-DNN粒子…

【Java基础教程】(二)入门介绍篇 · 下:从JDK下载安装到第一个“Hello World!”程序,解析PATH和CLASSPATH环境变量的妙用~

Java基础教程之入门介绍 下 本节学习目标1️⃣ JDK安装与配置2️⃣ 第一个Java程序&#xff1a;“Hello World!”3️⃣ 环境变量 CLASSPATH&#x1f33e; 总结 本节学习目标 JDK 安装与配置&#xff1b;理解环境变量PATH和CLASSPATH的主要作用&#xff1b;运行第一个Java程序…

TypeScript 自定义装饰器

&#xff08;预测未来最好的方法就是把它创造出来——尼葛洛庞帝&#xff09; 装饰器 装饰器一种更现代的代码模式&#xff0c;通过使用的形式注入在属性&#xff0c;寄存器&#xff0c;方法&#xff0c;方法参数和类中&#xff0c;比如在Angular&#xff0c;Nestjs和midway等…

E类变换器仿真

1 参数计算&#xff08;待续&#xff09; &#xff08;1&#xff09;确定振荡频率&#xff1a; &#xff08;2&#xff09;计算各器件参数&#xff1b; 2 电路仿真 &#xff08;1&#xff09;电路图 &#xff08;2&#xff09;电路分析 3 结果 &#xff08;1&#xff09;…

微信小程序+SpringBoot接入后台服务,接口数据来自后端

前言 前两天开发了一个微信小程序项目&#xff0c;只不过接口数据是自己设置的假数据。然后我就想将这些假数据替换掉。这些数据来自接口&#xff0c;之前做过前后端分离的项目&#xff0c;我就想能不能直接调用那些后端数据接口。结果是可以的。以下是自己编写的部分方法 步骤…

【IDE 小程序】小程序控制台 不打印 console.log问题

小程序控制台 不打印 console.log问题 全局搜索compress.drop_console&#xff08;一般在config文件中&#xff09;&#xff0c;设置为false&#xff0c;再重新打开小程序即可

【JUC-7】ReentrantLock (可重入锁)基础

ReentrantLock (可重入锁) ReentrantLock实现了Lock接口, 内部通过继承AQS, 实现了一个同步器. 可以通过同步器来创建Condition条件变量, 可以用作容器, 存放不同条件的等待线程. 说明ReentrantLock与AQS的关系 类图: 相对于synchronized, 都支持可重入. 它还具备如下特点: …

对弈人工智能!myCobot 280开源六轴机械臂Connect 4 四子棋对弈

Connect 4 myCobot280 Introduction Hi,guys.今天我们来介绍一下人工智能下棋&#xff0c;我们将用机械臂来作为对手跟你进行下棋。 人工智能下棋的研究可以追溯到20世纪50年代。当时&#xff0c;计算机科学家开始探索如何编写程序&#xff0c;使计算机能够下象棋。其中最著…

Linux 解决root用户被限制连接服务器

Linux 解决root用户被限制连接服务器 1. 问题描述2. 解决问题2.1 方式一&#xff08;忘记root密码的情况&#xff09;2.2 方式二&#xff08;知道root密码的情况&#xff09; 3. 其他 1. 问题描述 使用 root 用户不能链接服务器&#xff0c;密码对&#xff0c;就是连接不上&am…

VBA之正则表达式(42)-- 快速提取名称

实例需求&#xff1a;A列为待处理数据&#xff0c;现需要从中提取商品名、通用名、胰岛素笔相关信息&#xff0c;保存到B列至D列&#xff0c;需要注意如下几点&#xff1a; 胰岛素笔&#xff08;E列&#xff09;数据只存在于每组产品的第一行记录中&#xff0c;例如第2行数据中…

Apikit 自学日记:保存、使用测试用例

API测试用例是SaaS版本企业版才能使用的功能&#xff0c;免费版用户可通过付费升级后使用。 API管理应用中的测试用例管理涉及到两个场景&#xff1a;单接口测试用例管理 和 多接口测试用例批量测试。 一、单接口测试用例管理 功能入口&#xff1a;API管理应用 / 选中某个项目…