第十三章 模板

函數模板

函數模板使用

函數模板注意事項

自動類型推導,必須推導出一致的數據類型T,才可以使用

模板必須要確定出T的數據類型,才可以使用

普通函數和函數模板的類型轉化

普通函數隱式類型轉化(char轉int)

函數模板正常使用不會發生隱式類型轉化【自動推導】

函數模板隱式類型轉化(char轉int),需要指定類型

普通函數與函數模板調用

1. 如果函數模板和普通函數都可以實現,優先調用普通函數

普通函數實現的情況

普通函數只有聲明的情況

2. 可以通過空模板參數列表來強制調用函數模板

3. 函數模板也可以發生重載

4. 如果函數模板可以產生更好的匹配,優先調用函數模板

模板局限性

不能比較構造的類

解決方法:1、運算符重載 2、模板重載

模板重載:

類模板

類模板使用

類模板和函數模板區別

1. 類模板沒有自動類型推導的使用方式

2. 類模板在模板參數列表中可以有默認參數

類模板中成員函數創建時機

類模板對象做函數參數

1. 指定傳入的類型 --- 直接顯示對象的數據類型

2. 參數模板化 --- 將對象中的參數變為模板進行傳遞

3. 整個類模板化 --- 將這個對象類型 模板化進行傳遞

類模板與繼承

指定類型

子類變類模板

類模板成員函數類外實現

類模板分文件編寫

person.h文件:

#pragma once
#include <iostream>
using namespace std;template<class T1, class T2>
class Person {
public:T1 m_Name;T2 m_Age;Person(T1 name, T2 age);	//只聲明void show();};

person.cpp文件:

#include "person.h"template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)	//類模板的類外實現
{this->m_Name = name;this->m_Age = age;
}template<class T1, class T2>
void Person<T1, T2>::show()
{cout << this->m_Name << " " << this->m_Age << endl;
}

測試代碼

void test() {Person<string,int> p("張三",2);p.show();
}

解決方式1:直接包含.cpp源文件

解決方式2:將聲明和實現寫到同一個文件中,并更改后綴名為.hpp,hpp是約定的名稱,并不是強制

將person.h文件改為person.hpp文件【約定俗成的后綴,代表類模板】:

#pragma once
#include <iostream>
using namespace std;template<class T1, class T2>
class Person {
public:T1 m_Name;T2 m_Age;Person(T1 name, T2 age);	//只聲明void show();};template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)	//類模板的類外實現
{this->m_Name = name;this->m_Age = age;
}template<class T1, class T2>
void Person<T1, T2>::show()
{cout << this->m_Name << " " << this->m_Age << endl;
}

類模板與友元

全局函數類內實現 - 直接在類內聲明友元即可

全局函數類外實現 - 需要提前讓編譯器知道全局函數的存在

類模板案例

屬性設置

private:T* pAddress;		//指針指向在堆區開辟的數組起始地址int m_Capacity;		//數組容量【總體容量】int m_Size;			//數組大小【占有的數據量】

構造函數實現

根據輸入的容量進行初始化

	MyArray(int capacity) {		//有參構造,根據容量進行初始化this->m_Capacity = capacity;this->m_Size = 0;this->pAddress = new T[this->m_Capacity];}

根據已有的數組進行初始化

	//拷貝【防止淺拷貝問題】//構造時拷貝【當參數被聲明為 const 時,函數內部不能修改這個參數的值。有助于防止意外修改傳入的數據,提高代碼的安全性和可維護性。】MyArray(const MyArray& arr) {		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_Size; i++)this->pAddress[i] = arr.pAddress[i];}

析構函數實現

	~MyArray() {		//析構函數,如果堆區不為空,清空,防止出現野指針if (this->pAddress != NULL) {delete[] this->pAddress;}}

重載運算符“=”

	//重載運算符“=”,防止出現淺拷貝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_Size; i++)this->pAddress[i] = arr.pAddress[i];//返回對象本身//【this存放指向該對象的地址,*this解引用即是對象本身,MyArray&代表引用】//【最終效果就是返回對象本身的引用(引用可以理解為別名,使用引用可以訪問該對象)】return *this;				}

實現訪問堆區數據

添加數據

	//尾插法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& operator[](int index) {		//返回引用是為了防止出現arr[i] = 10的賦值情況return this->pAddress[index];}

顯示記錄的參數

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

MyArray.hpp總的實現

#pragma once
#include <iostream>
using namespace std;template<class T>
class MyArray {
public:MyArray(int capacity) {		//有參構造,根據容量進行初始化this->m_Capacity = capacity;this->m_Size = 0;this->pAddress = new T[this->m_Capacity];}//拷貝【防止淺拷貝問題】MyArray(const MyArray& arr) {		//構造時拷貝【當參數被聲明為 const 時,函數內部不能修改這個參數的值。這有助于防止意外修改傳入的數據,提高代碼的安全性和可維護性。】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_Size; i++)this->pAddress[i] = arr.pAddress[i];}//重載運算符“=”,防止出現淺拷貝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_Size; i++)this->pAddress[i] = arr.pAddress[i];//返回對象本身//【this存放指向該對象的地址,*this解引用即是對象本身,MyArray&代表引用】//【最終效果就是返回對象本身的引用(引用可以理解為別名,使用引用可以訪問該對象)】return *this;				}//尾插法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& operator[](int index) {		//返回引用是為了防止出現arr[i] = 10的賦值情況return this->pAddress[index];}//返回數組容量int getCapacity() {return this->m_Capacity;}//返回數組大小int getSize() {return this->m_Size;}~MyArray() {		//析構函數,如果堆區不為空,清空,防止出現野指針if (this->pAddress != NULL) {delete[] this->pAddress;}}private:T* pAddress;		//指針指向在堆區開辟的數組起始地址int m_Capacity;		//數組容量【總體容量】int m_Size;			//數組大小【占有的數據量】};

測試代碼

class Person {
public:string m_Name;int m_Age;Person() {};Person(string name, int age){this->m_Name = name;this->m_Age = age;}void show(){cout << this->m_Name << " " << this->m_Age << endl;}};void test() {MyArray<int> arr1(5);//MyArray<int> arr2(arr1);//MyArray<int> arr3(100);//arr3 = arr1;for (int i = 0; i < arr1.getCapacity(); i++)arr1.Push_Back(i);cout << "=====================arr1<int>=======================" << endl;cout << "capacity: " << arr1.getCapacity() << endl;cout << "size " << arr1.getSize() << endl;for (int i = 0; i < arr1.getSize(); i++)cout << arr1[i] << endl;arr1.Pop_Back();cout << "==============arr1尾刪后================" << endl;cout << "capacity: " << arr1.getCapacity() << endl;cout << "size " << arr1.getSize() << endl;for (int i = 0; i < arr1.getSize(); i++)cout << arr1[i] << endl;MyArray<char> arr2(6);for (int i = 0; i < arr2.getCapacity(); i++)arr2.Push_Back(i+97);cout << "====================arr2<char>=========================" << endl;cout << "capacity: " << arr2.getCapacity() << endl;cout << "size " << arr2.getSize() << endl;for (int i = 0; i < arr2.getSize(); i++)cout << arr2[i] << endl;MyArray<Person> arr3(3);for (int i = 0; i < arr3.getCapacity(); i++) {Person p("man"+ std::to_string(i), i);arr3.Push_Back(p);}cout << "====================arr3<Person>=========================" << endl;cout << "capacity: " << arr3.getCapacity() << endl;cout << "size " << arr3.getSize() << endl;for (int i = 0; i < arr3.getSize(); i++)arr3[i].show();}

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

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

相關文章

云計算-專有網絡VPC

&#x1f310; 什么是 VPC&#xff1f;&#xff08;Virtual Private Cloud&#xff09; VPC&#xff08;Virtual Private Cloud&#xff0c;虛擬私有云&#xff09; 是公有云服務商提供的一種網絡隔離服務&#xff0c;允許用戶在云中創建一個邏輯隔離的私有網絡環境。你可以在這…

關于*gin.Context的理解

關于*gin.Context的理解 作為初學者&#xff0c;在學習go語言用gin開發web時&#xff0c;我對*gin.Context感到困惑。本文章以自我總結為主&#xff0c;大部分為來自詢問ai后的總結&#xff0c;如有問題歡迎指出。 *gin.Context可以理解為一個gin框架的上下文對象指針&#x…

Qt中的OpenGL (6)[坐標系統]

文章目錄 文章說明學習目標目錄結構坐標系統局部空間世界空間觀察空間裁剪空間正射投影矩陣透視投影矩陣組合進入3D世界頂點數據著色器設置數據矩陣設置文章說明 本文是學習OpenGL的筆記,主要參考大神JoeyDeVries的LearnOpenGL第八課《坐標系統》,并將教程中的代碼基于Qt進行…

Spring Aop @After (后置通知)的使用場景?

核心定義 After 是 Spring AOP 中的另一種通知&#xff08;Advice&#xff09;類型&#xff0c;通常被稱為“后置通知”或“最終通知”。 它的核心作用是&#xff1a; 無論目標方法是正常執行完成&#xff0c;還是在執行過程中拋出了異常&#xff0c;After 通知中的代碼 總是…

UNet改進(4):交叉注意力(Cross Attention)-多模態/多特征交互

在計算機視覺領域&#xff0c;UNet因其優異的性能在圖像分割任務中廣受歡迎。本文將介紹一種改進的UNet架構——UNetWithCrossAttention&#xff0c;它通過引入交叉注意力機制來增強模型的特征融合能力。 1. 交叉注意力機制 交叉注意力(Cross Attention)是一種讓模型能夠動態地…

C#里從CSV文件加載BLOB數據字段到數據庫的處理

大量的數據保存在CSV文件, 當需要把這些數據加載到數據庫,然后使用數據庫來共享出去。 就需要把CSV文件導入數據庫, 怎么樣快速地把CSV文件導入數據庫呢? 這個就需要使用類MySqlBulkLoader,它是mariadb數據庫快速導入的方式。 一般使用SQL語句導入是10秒,那么使用這種方…

【后端】負載均衡

長期不定期更新補充。 定義 負載均衡&#xff08;Load Balancing&#xff09;是指將來自客戶端的請求合理分發到多個服務器或服務節點&#xff0c;以提高系統性能、可用性與可靠性。 分工 前端不做負載均衡&#xff0c;前端只發請求&#xff0c;不知道請求去哪臺服務器。 負…

記錄一次:Java Web 項目 CSS 樣式/圖片丟失問題:一次深度排查與根源分析

記錄一次&#xff1a;Java Web 項目 CSS 樣式/圖片丟失問題&#xff1a;一次深度排查與根源分析 **記錄一次&#xff1a;Java Web 項目 CSS 樣式丟失問題&#xff1a;一次深度排查與根源分析****第一層分析&#xff1a;資源路徑問題****第二層分析&#xff1a;服務端跳轉邏輯**…

torchmd-net開源程序是訓練神經網絡潛力

?一、軟件介紹 文末提供程序和源碼下載 TorchMD-NET 提供最先進的神經網絡電位 &#xff08;NNP&#xff09; 和訓練它們的機制。如果有多個 NNP&#xff0c;它可提供高效、快速的實現&#xff0c;并且它集成在 GPU 加速的分子動力學代碼中&#xff0c;如 ACEMD、OpenMM 和 …

在Docker上安裝Mongo及Redis-NOSQL數據庫

應用環境 Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-139-generic x86_64) Docker version 28.1.1, build 4eba377 文章目錄 一、部署Mongo1. 拉取容器鏡像2. 生成Run腳本2.1 準備條件2.2 參數解讀2.3 實例腳本 3. 實例操作3.1 Mongo bash控制臺3.2 庫表操作 4. MongoDB Compass (G…

Java 編程之責任鏈模式

一、什么是責任鏈模式&#xff1f; 責任鏈模式&#xff08;Chain of Responsibility Pattern&#xff09; 是一種行為型設計模式&#xff0c;它讓多個對象都有機會處理請求&#xff0c;從而避免請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈&#xff0c;沿著這條…

1、做中學 | 一年級上期 Golang簡介和安裝環境

一、什么是golang Golang&#xff0c;通常簡稱 Go&#xff0c;是由 Google 公司的 Robert Griesemer、Rob Pike 和 Ken Thompson 于 2007 年創建的一種開源編程語言&#xff0c;并在 2009 年正式對外公布。 已經有了很多編程語言&#xff0c;為什么還要創建一種新的編程語言&…

Linux--迷宮探秘:從路徑解析到存儲哲學

上一篇博客我們說完了文件系統在硬件層面的意義&#xff0c;今天我們來說說文件系統在軟件層是怎么管理的。 Linux--深入EXT2文件系統&#xff1a;數據是如何被組織、存儲與訪問的&#xff1f;-CSDN博客 &#x1f30c; 引言&#xff1a;文件系統的宇宙觀 "在Linux的宇宙中…

淘寶商品數據實時獲取方案|API 接口開發與安全接入

在電商數據獲取領域&#xff0c;除了官方 API&#xff0c;第三方數據 API 接入也是高效獲取淘寶商品數據的重要途徑。第三方數據 API 憑借豐富的功能、靈活的服務&#xff0c;為企業和開發者提供了多樣化的數據解決方案。本文將聚焦第三方數據 API 接入&#xff0c;詳細介紹其優…

什么是防抖和節流?它們有什么區別?

文章目錄 一、防抖&#xff08;Debounce&#xff09;1.1 什么是防抖&#xff1f;1.2 防抖的實現 二、節流&#xff08;Throttle&#xff09;2.1 什么是節流&#xff1f;2.2 節流的實現方式 三、防抖與節流的對比四、總結 在前端開發中&#xff0c;我們經常會遇到一些高頻觸發的…

Springboot集成阿里云OSS上傳

Springboot集成阿里云OSS上傳 API 接口描述 DEMO提供的四個API接口&#xff0c;支持不同方式的文件和 JSON 數據上傳&#xff1a; 1. 普通文件上傳接口 上傳任意類型的文件 2. JSON 字符串上傳接口 上傳 JSON 字符串 3. 單個 JSON 壓縮上傳接口 上傳并壓縮 JSON 字符串…

刪除大表數據注意事項

數據庫是否會因刪除操作卡死&#xff0c;沒有固定的 “安全刪除條數”&#xff0c;而是受數據庫配置、表結構、操作方式、當前負載等多種因素影響。以下是關鍵影響因素及實踐建議&#xff1a; 一、導致數據庫卡死的核心因素 硬件與數據庫配置 CPU / 內存瓶頸&#xff1a;刪除…

Redis 是單線程模型?|得物技術

一、背景 使用過Redis的同學肯定都了解過一個說法&#xff0c;說Redis是單線程模型&#xff0c;那么實際情況是怎樣的呢&#xff1f; 其實&#xff0c;我們常說Redis是單線程模型&#xff0c;是指Redis采用單線程的事件驅動模型&#xff0c;只有并且只會在一個主線程中執行Re…

[特殊字符] AIGC工具深度實戰:GPT與通義靈碼如何徹底重構企業開發流程

&#x1f50d; 第一模塊&#xff1a;理念顛覆——為什么AIGC不是“玩具”而是“效能倍增器”&#xff1f; ▍企業開發的核心痛點圖譜&#xff08;2025版&#xff09; ??研發效能瓶頸??&#xff1a;需求膨脹與交付時限矛盾持續尖銳&#xff0c;傳統敏捷方法論已觸天花板?…

(LeetCode 面試經典 150 題) 169. 多數元素(哈希表 || 二分查找)

題目&#xff1a;169. 多數元素 方法一&#xff1a;二分法&#xff0c;最壞的時間復雜度0(nlogn)&#xff0c;但平均0(n)即可。空間復雜度為0(1)。 C版本&#xff1a; int nnums.size();int l0,rn-1;while(l<r){int mid(lr)/2;int ans0;for(auto x:nums){if(xnums[mid]) a…