類模版的相關案例

案例實現:實現一個通用的數組類,要求如下:

  • 可以對內置數據類型以及自定義數據類型的數據進行存儲
  • 將數組中的數據存儲到堆區
  • 構造函數中可以傳入數組的容量
  • 提供對應的拷貝構造函數以及operator=防止淺拷貝問題
  • 提供尾插法和尾刪法對數組中的數據進行增加和刪除
  • 可以通過下標的方式訪問數組中的元素
  • 可以獲取數組中當前元素個數和數組的容量

因為我們并不知道里面有什么數據類型,因此我們需要將這些數據進行模版化

首先我們在MyArray.hpp文件里面寫入以下的代碼

//自己的通用的數組類
#include <iostream>
using namespace std;template<typename T>
class MyArray{public://有參構造函數 參數 容量MyArray(int capacity){cout<<"MyArray有參構造調用"<<endl;this->m_Capacity=capacity;//數組初始化的大小為0this->m_Size=0;this->pAddress=new T[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];//將原數組的元素拷貝到新數組中for(int i=0;i<this->m_Capacity;i++){this->pAddress[i]=arr.pAddress[i];}}//operator= 也是為了防止淺拷貝問題. a=b=cMyArray &operator=(const MyArray &arr){cout<<"MyArray賦值運算符調用"<<endl;//先判斷原來堆區是否有數據,如果有先釋放if(this->pAddress!=nullptr){delete[] this->pAddress;this->pAddress=nullptr;//防止其為一個野指針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;//返回當前對象的引用}//之后再去做一個深拷貝//析構函數~MyArray(){if(this->pAddress!=nullptr){cout<<"MyArray析構函數調用"<<endl;delete[] this->pAddress;//防止其為一個野指針this->pAddress=nullptr;}}private:T* pAddress; //指針指向堆區開辟的真實的數組int m_Capacity;//數組的容量int m_Size;//數組的元素個數(數組的大小)
};

在數組類封裝.cpp這個文件里面寫入下面的代碼

#include <iostream>
using namespace std;
#include "MyArray.hpp"void test01()
{MyArray<int> arr1(5); // 創建一個容量為5的數組MyArray<int> arr2(arr1); // 使用拷貝構造函數創建一個新數組MyArray<int> arr3(100); // 使用賦值運算符進行賦值arr3=arr1;// 使用賦值運算符進行賦值
}int main()
{test01(); // 測試函數return 0; // 返回0表示程序正常結束
}

之后運行,我們可以得到以下的內容

也就是說我們這幾個進行了深拷貝,還有有參構造,之后通過析構函數釋放了它們的內存。

MyArray.hpp

//自己的通用的數組類
#include <iostream>
using namespace std;template<typename T>
class MyArray{public://有參構造函數 參數 容量MyArray(int capacity){this->m_Capacity=capacity;//數組初始化的大小為0this->m_Size=0;this->pAddress=new T[capacity]; //開辟堆區空間}//為了防止淺拷貝的問題,還必須寫一個拷貝構造函數MyArray(const MyArray &arr){this->m_Capacity=arr.m_Capacity;this->m_Size=arr.m_Size;//潛拷貝//this->pAddress=arr.pAddress; //將原數組的地址賦值給新數組//開辟新的堆區空間this->pAddress=new T[arr.m_Capacity];//將原數組的元素拷貝到新數組中for(int i=0;i<this->m_Capacity;i++){this->pAddress[i]=arr.pAddress[i];}}//operator= 也是為了防止淺拷貝問題. a=b=cMyArray &operator=(const MyArray &arr){//先判斷原來堆區是否有數據,如果有先釋放if(this->pAddress!=nullptr){delete[] this->pAddress;this->pAddress=nullptr;//防止其為一個野指針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;//返回當前對象的引用}//尾插法//一般為了防止T被修改,因此我們一般會寫入一個const修飾符void Push_Back(const T &val){//判斷數組是否已滿if(this->m_Size>=this->m_Capacity)  {cout<<"數組已滿,無法插入元素"<<endl;return;}else{this->pAddress[this->m_Size]=val; //將元素插入到數組的末尾this->m_Size++;//元素個數加1}}//尾刪法void Pop_Back(){if(this->m_Size<=0){cout<<"數組為空,無法刪除元素"<<endl;return;}else{//讓用戶訪問不到最后一個元素就可以了this->m_Size--;//元素個數減1//不需要刪除最后一個元素,因為數組的大小已經減小了}}//通過下標的方式訪問數組中的元素T& operator[](int index){return this->pAddress[index]; //返回數組中指定下標的元素}//返回數組的容量int GetCapacity() const{return this->m_Capacity;}//返回數組的大小int GetSize() const{return this->m_Size;}//析構函數~MyArray(){if(this->pAddress!=nullptr){delete[] this->pAddress;//防止其為一個野指針this->pAddress=nullptr;}}private:T* pAddress; //指針指向堆區開辟的真實的數組int m_Capacity;//數組的容量int m_Size;//數組的元素個數(數組的大小)
};

數組類封裝函數那里寫

#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); // 創建一個容量為5的數組for(int i=0;i<5;i++){arr1.Push_Back(i); // 向數組中添加元素}cout<<"arr1的打印輸出為:"<<endl;// MyArray<int> arr2(arr1); // 使用拷貝構造函數創建一個新數組// MyArray<int> arr3(100); // 使用賦值運算符進行賦值// arr3=arr1;printIntArray(arr1); // 打印數組內容cout<<"arr1的容量為:"  << arr1.GetCapacity() << endl; // 打印數組容量 cout<<"arr1的大小為:"  << arr1.GetSize() << endl; // 打印數組大小MyArray<int> arr2(arr1); // 使用拷貝構造函數創建一個新數組cout<<"arr2的打印輸出為:"<<endl;arr2.Pop_Back(); // 刪除數組的最后一個元素printIntArray(arr2); // 打印刪除后的數組內容cout<<"刪除一個元素后,arr2的大小為:"  << arr2.GetSize() << endl; // 打印數組大小cout<<"刪除一個元素后,arr2的容量為:"  << arr2.GetCapacity() << endl; // 打印數組容量}//測試自定義的數據類型class Person{public:Person() {}Person(string name,int age): m_Name(name),m_Age(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<<" 年齡: "<<arr[i].m_Age<<endl;}}void test02(){MyArray<Person> arr3(10);Person p1("孫悟空",500);Person p2("豬八戒",300);Person p3("沙和尚",400);Person p4("唐僧",1000);Person p5("白龍馬",200);Person p6("小白龍",150);Person p7("小紅龍",120);arr3.Push_Back(p1);arr3.Push_Back(p2);arr3.Push_Back(p3);arr3.Push_Back(p4);arr3.Push_Back(p5);arr3.Push_Back(p6);arr3.Push_Back(p7); //打印數組printPersonArray(arr3); // 這里需要重載printIntArray函數來打印Person類型的數組}int main()
{test01(); // 測試函數cout << "------------------------" << endl;cout << "測試自定義數據類型的數組" << endl;cout << "------------------------" << endl;cout << "測試自定義數據類型的數組" << endl;test02(); // 測試函數return 0; // 返回0表示程序正常結束
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/89316.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/89316.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/89316.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

服務器端安全檢測與防御技術概述

一、服務器安全風險1.不必要的訪問&#xff08;如只提供HTTP服務&#xff09;--應用識別控制2.公網發起IP或端口掃描、DDOS攻擊等--防火墻3.漏洞攻擊&#xff08;針對服務器操作系統等&#xff09;--IPS4.根據軟件版本的已知漏洞進行攻擊&#xff0c;口令暴力破解、獲取用戶權限…

前端性能與可靠性工程系列: 渲染、緩存與關鍵路徑優化

前端性能與可靠性工程系列: 渲染、緩存與關鍵路徑優化 第一部分:揭秘瀏覽器 - 關鍵渲染路徑 (CRP) 關鍵渲染路徑 (Critical Rendering Path - CRP) 是指瀏覽器從接收到最初的 HTML、CSS 和 JavaScript 字節,到最終將它們渲染成可見像素所必須經過的一系列步驟。我們的目標,…

基于CentOS的分布式GitLab+Jenkins+Docker架構:企業級CI/CD流水線實戰全記錄

引言&#xff1a;從單機到分布式容器架構的演進在傳統Web應用部署中&#xff0c;我們常常面臨環境不一致、部署效率低下等問題。我曾經維護過一個需要手動在5臺服務器上重復部署的游戲項目&#xff0c;每次發布都如同走鋼絲。本文將詳細分享如何基于CentOS系統&#xff0c;構建…

JVM——為什么Java8移除了永久代(PermGen)并引入了元空間(Metaspace)?

Java8移除永久代并引入元空間&#xff0c;主要是為了解決 PermGen 固定大小、容易導致內存溢出、GC 效率低的問題。元空間使用本地內存&#xff0c;具備更靈活的內存分配能力&#xff0c;提升了垃圾收集和內存管理的效率。 PermGen 的局限性 ①固定大小:永久代的內存空間大小在…

3.正則化——新聞分類

影響結果出了最終的目標&#xff0c;還會有許多細節因素 在機器學習中&#xff0c;往往會面臨很多過擬合和欠擬合的問題。 欠擬合是訓練不到位&#xff0c;過擬合是訓練過頭&#xff0c;會導致泛化性差正則化是在損失函數中添加一個懲罰項&#xff0c;以簡化模型對于懲罰項Pena…

HTML的重要知識

什么是HTMLHTML是Hyper Text Markup Language的縮寫&#xff0c;意思是超文本標記語言。標簽標題標簽&#xff1a;————-h1,h2,h3.....段落標簽 &#xff1a;————p換行標簽&#xff1a; ————br列表標簽&#xff1a;有序列表&#xff1a;——ol無序列表&#xff1a;—…

【C語言網絡編程】HTTP 客戶端請求(發送請求報文過程)

在 C 語言中&#xff0c;我們可以使用 socket 編程來手動實現一個簡單的 HTTP 客戶端&#xff0c;像瀏覽器一樣請求網頁數據。本文將結合實際代碼&#xff0c;重點講解如何通過 C 語言構造并發送一個 HTTP 請求報文&#xff0c;實現與服務器的基本通信。 文章目標 通過一個簡單…

oracle2kingbase的字段長度問題

實驗一&#xff1a; oracle中&#xff1a; create table testlen(c1 varchar2(2)); insert into testlen values(山); --成功 insert into testlen values(山西); --失敗 ORA-12899: 列 "TESTK"."TESTLEN"."C1" 的值太大 (實際值: 4, 最大值: 2…

單鏈表的題目,咕咕咕

1.咕 203. 移除鏈表元素 - 力扣&#xff08;LeetCode&#xff09; 給你一個鏈表的頭節點 head 和一個整數 val &#xff0c;請你刪除鏈表中所有滿足 Node.val val 的節點&#xff0c;并返回 新的頭節點 struct ListNode* removeElements(struct ListNode* head, int val) …

關于程序=數據結構+算法這句話最近的一些思考

最近看了很多單片機STM32的的相關程序&#xff0c;尤其是設計到ringbuff、buffer_manage、os_memory預計mem_manage等程序中間層的用法&#xff0c;我對這句話有了一些更深的思考&#xff0c;現在記錄下來&#xff0c;希望對處于相同階段的程序一些思想啟迪。首先“數據結構”也…

Rust 錯誤處理

Rust 錯誤處理 引言 Rust 是一種系統編程語言&#xff0c;以其安全、并發和性能著稱。在 Rust 中&#xff0c;錯誤處理是一個核心概念&#xff0c;它確保了程序在遇到異常情況時能夠優雅地處理。本文將深入探討 Rust 中的錯誤處理機制&#xff0c;包括錯誤類型、錯誤傳播、錯誤…

17. 什么是 webSocket ?

總結 WebSocket 是 HTML5 引入的一種新協議&#xff0c;允許客戶端和服務器之間進行雙向實時通信。建立在 TCP 協議之上&#xff0c;默認端口是 80&#xff08;ws&#xff09; 和 443&#xff08;wss&#xff09;&#xff0c;沒有同源限制&#xff0c;客戶端可以與任意服務器通…

從零開始跑通3DGS教程:(五)3DGS訓練

寫在前面 本文內容 所屬《從零開始跑通3DGS教程》系列文章; 本文介紹在docker中訓練3dgs的方法 平臺/環境 linux, nvidia GPU, docker 轉載請注明出處: https://blog.csdn.net/qq_41102371/article/details/146535874 目錄 寫在前面系列文章準備docker創建環境參考完系列文章…

日記_7.14_實際開發的進步

1、快速定位后端2、會定位前端啦啦啦&#xff01;3、前端沒有意義的塊叫div和span。而不是script4、所有 JavaScript 標識符均 區分大小寫5、JS中$和_下劃線和doller符均被視為字母。6、var、let區別&#xff1a;1 var全局。let局部。2 var可以重新聲明格式&#xff0c;let之恩…

AI Agent 開發

Agent開發常用框架&#xff1a; LangChainLlamaIndexVercel AI SDK LangChain&#xff1a;一站式 LLM 應用開發框架一句話總結 LangChain 把「模型調用 外部數據 工具 記憶 流程編排」全部標準化&#xff0c;讓你像搭積木一樣快速組合出聊天機器人、RAG、Agent 等大模型應用…

【水動力學】04 二維洪水淹沒模型Pypims安裝

模型介紹 HiPIMS&#xff08;High-Performance Integrated hydrodynamic Modelling System&#xff09;使用最先進的數值方案&#xff08;Godunov型有限體積法&#xff09;來求解二維淺水方程以進行洪水模擬。為了支持高分辨率洪水模擬&#xff0c;使用CUDA/C 語言在多個GPU上…

ARC 03 從Github Action job 到 runner pod

Github Action job 分配到集群 背景 job 是 Github Action 的基本單位&#xff0c;每個 job 單獨分配一個 runner。workflow 由一個或者多個 job 組成。如果用戶觸發runs-on字段為arc-runner-set的 job&#xff0c;那么 Github Action 服務器將 job 分配給 listener pod。 源碼…

ubuntu 22.04 anaconda comfyui安裝

背景&#xff1a; 戴爾R740服務器&#xff0c;安裝了proxmox操作系統&#xff0c;配置了顯卡直通。創建了一個ubuntu 22.04 VM虛擬機實例&#xff0c;并安裝了顯卡驅動與cuda等相關配置&#xff1a; 接下來準備搭建一套comfyui的環境&#xff0c;前段時間B站&#xff0c;抖音各…

每日面試題04:volatile字段的原理

在之前面試題02ConcurrentHashMap的底層原理中提到了volatile修飾符&#xff0c;在多線程編程的世界里&#xff0c;數據同步是一道繞不開的坎。當多個線程同時操作共享變量時&#xff0c;“看不見對方的修改”或“代碼順序錯亂”往往會導致程序行為異常。而 volatile作為 Java …

【云原生網絡】Istio基礎篇

文章目錄概述基礎知識技術架構概述數據平面核心組件網絡代理Envoy控制平面核心組件xDS協議Pilot組件其他概述參考博客&#x1f60a;點此到文末驚喜?? 概述 基礎知識 背景知識 服務網格&#xff08;Service Mesh&#xff09;&#xff1a;獨立于應用程序的基礎設施層&#x…