02.類模板

2、類模板

2.1 類模板語法

建立一個通用類,類中的成員、數據類型可以不具體制定,用一個虛擬的類型來代表。

template<typename T>
// 類
  • template:聲明創建模板
  • typename:表名其后面的符號是一種數據類型,可以用 class 代替
  • T:通用的數據類型,名稱可以替換,通常為大寫字母
#include <iostream>
using namespace std;
// 類模板
template<class NameType, class AgeType>
class Person {public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}  void showPerson() {cout << "name: " << this->mName << "age: " << this->mAge << endl;}public:NameType mName;AgeTyep mAge;
};void test01() {// 指定 NameType 為 string 類型,AgeType 為 int 類型Person<string,int>P1("孫悟空",999);P1.showPerson();
}int main() {test01();system("pause");return 0;
}

總結:

  • 類模板和函數模板語法類似,在聲明模板 template 后面加類,此類稱為類模板

2.2 類模板和函數模板的區別

  • 類模板沒有自動類型推導的使用方式
  • 類模板在模板參數列表中可以有默認參數
#include <iostream>
using namespace std;
// 類模板
template<class NameType, class AgeType = int>
class Person {public:Person(nameType name, AgeType age) {this->mName = name;this->mAge = age;}void showPerson() {cout << "name: " << this->mName << "age: " << this->mAge << endl;}public:NameType mName;AgeType mAge;
};//1、類模板沒有自動類型推導的使用方式
//1、類模板沒有自動類型推導的使用方式
void test01()
{// Person p("孫悟空", 1000); 			// 錯誤 類模板使用時候,不可以用自動類型推導Person <string ,int>p("孫悟空", 1000); // 必須使用顯示指定類型的方式,使用類模板p.showPerson();
}//2、類模板在模板參數列表中可以有默認參數
void test02() {Person<string>p("豬八戒",999);			// 類模板中的模板參數列表,庫指定默認參數p.showPerson();
}int main() {test01();test02();system("pause");return 0;
}

總結:

  • 類模板使用只能用顯示指定類型方式
  • 類模板中的模板參數列表可以有默認參數

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

類模板中成員函數和普通類中成員函數創建時機是有區別的:

  • 普通類中的成員函數一開始就可以創建
  • 類模板中的成員函數在調用時才創建
#include <iostream>
using namespace std;
class Person1 {public:void showPerson1() {cout << "Person1 show" << endl;}
};
class Person2 {public:void showPerson2() {cout << "Person2 show" << endl;}
};template<class T>class MyClass {public:T obj;// 類模板中的成員函數,并不是一開始就創建的,而是在模板調用時再生成void fun1() { obj.showPerson1(); }void fun2() { obj.showPerson2(); }};
void test01()
{MyClass<Person1> m;m.fun1();// m.fun2();		// 編譯會出錯,說明函數調用才會去創建成員函數
}
int main() {test01();system("pause");return 0;
}

總結:

  • 類模板中的成員函數并不是一開始就創建的,在調用時才去創建

2.4 類模板對象做函數參數

  • 類模板實例化出的對象,向函數傳參的方式

共三種傳入方式:

  1. 指定傳入的類型:直接顯示對象的數據類型
  2. 參數模板化:將對象中的參數變為模板進行傳遞
  3. 整個類模板化:將這個對象類型模板化進行傳遞
#include <iostream>
#include <string>
using namespace std;// 類模板
template<class NameType, class AgeType = int>
class Person {
public:Person(NameType name, AgeType age) {this->mName = name;this->mAge = age;}void showPerson() {cout << "name: " << this->mName << " age: " << this->mAge << endl;}public:NameType mName;AgeType mAge;
};// 1、類模板對象作為函數參數,方式一:指定傳入的類型
void printPerson1(Person<string, int>& p) {p.showPerson();
}
void test01() {Person<string, int>p("孫悟空", 100);printPerson1(p);
}// 2、參數模板化
template<class T1, class T2>
void printPerson2(Person<T1, T2>& p) {p.showPerson();cout << "T1的類型為: " << typeid(T1).name() << endl;cout << "T2的類型為: " << typeid(T2).name() << endl;
}
void test02() {Person<string, int>p("豬八戒", 90);printPerson2(p);
}// 3、整個類模板化
template<class T>
void printPerson3(T& p) {cout << "T的類型為: " << typeid(T).name() << endl;p.showPerson();
}
void test03() {Person<string, int>p("唐僧", 30);printPerson3(p);
}int main() {test01();test02();test03();system("pause");return 0;
}

總結:

  • 通過類模板創建的對象,可以有三種方式向函數中進行傳參
  • 使用比較廣泛的是第一種:指定傳入的類型

2.5 類模板與繼承

當類模板碰到繼承時,需要注意以下幾點:

  • 當子類繼承的父類是一個類模板時,子類在聲明的時候,要指定出父類中 T 的類型
  • 如果不指定,編譯器無法給子類分配內存
  • 如果想靈活指定出父類中T的類型,子類也需變為類模板

2.6 類模板成員函數類外實現

#include <iostream>
using namespace std;// 類模板中成員函數類外實現
template<class T1,class T2>
class Person {
public:// 成員函數類內聲明Person(T1 name, T2 age);void showPerson();public:T1 m_Name;T2 m_Age;
};// 構造函數 類外實現
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>::showPerson() {cout << "姓名:" << this->m_Name << " 年齡:" << this->m_Age << endl;
}void test01() {Person<string, int>p("Tom", 20);p.showPerson();
}
int main() {test01();system("pause");return 0;
}

總結:

  • 類模板中成員函數類外實現時,需要加上模板參數列表

2.7 類模板和友元

  • 全局函數類內實現:直接在類內聲明友元即可
  • 全局函數類外實現:需要提前讓編譯器知道全局函數的存在
#include <iostream>
#include <string>
using namespace std;// 2、全局函數配合友元 類外實現:先做函數模板聲明,下方在做函數模板定義,在做友元
template<class T1, class T2>class Person;// 如果聲明了函數模板,可以將實現寫到后面,否則需要將實現體寫到類的前面讓編譯器提前看到
template<class T1, class T2> void printPerson2(Person<T1, T2>& p);template<class T1,class T2>
class Person {// 1、全局函數配合友元   類內實現friend void printPerson(Person<T1, T2>& p) {cout << "姓名:" << p.m_Name << "年齡:" << p.m_Age << endl;}//   全局函數配合友元   類外實現friend void printPerson2<>(Person<T1, T2>& p);public:Person(T1 name, T2 age) {this->m_Name = name;this->m_Age = age;}private:T1 m_Name;T2 m_Age;
};// 1、全局函數在類內實現
void test01() {Person <string, int>p("Tom", 20);printPerson(p);
}// 2、全局函數在類外實現
void test02() {Person<string, int>p("Jerry", 30);printPerson2(p);
}template<class T1, class T2>
void printPerson2(Person<T1, T2>& p) {cout << "類外實現 --- 姓名:" << p.m_Name << "年齡:" << p.m_Age << endl;
}int main() {test01();test02();system("pause");return 0;
}

總結:

  • 建議全局函數做類內實現,用法簡單,而且編譯器可以直接識別

2.8 類模板案例

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

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

myArray.hpp文件

#pragma
#include <iostream>
#include <string>
using namespace std;template<class T>
class MyArray {
public:// 構造函數MyArray(int capatity) {this->m_Capacity = capatity;this->m_Size = 0;pAddress = new T[this->m_Capacity];}// 拷貝函數MyArray(const MyArray& arr) {this->m_Capacity = arr.m_Capacity;this->m_Size = arr.m_Size;this->pAddress = new T[this->m_Capacity];for (int i = 0; i < this->m_Size; ++i) {// 如果T為對象,而且還包含指針,必須需要重載 = 操作符,因為這個等號不是構造 而是賦值,// 普通類型可以直接 = 但是指針類型需要深拷貝this->pAddress[i] = arr.pAddress[i];}}// 重載 = 操作符 防止淺拷貝問題MyArray& operator=(const MyArray& myarray) {if (this->pAddress != nullptr) {delete[] this->pAddress;this->m_Capacity = 0;this->m_Size = 0;}this->m_Capacity = myarray.m_Capacity;this->m_Size = myarray.m_Size;this->pAddress = new T[this->m_Capacity];for (int i = 0; i < this->m_Size; ++i) {this->pAddress[i] = myarray[i];}return *this;}// 重載 [] 操作符 arr[0]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 != nullptr) {delete[] this->pAddress;this->pAddress = nullptr;this->m_Capacity = 0;this->m_Size = 0;}}
private:T* pAddress;	// 指向一個堆空間,這個空間存儲真正的數據int m_Capacity; // 容量int m_Size;		// 大小
};

myArray.cpp文件

#include "myArray.hpp"void printIntArray(MyArray<int>& arr) {for (int i = 0; i < arr.getSize(); ++i) {cout << arr[i] << " ";}cout << endl;
}// 測試內置數據類型
void test01() {MyArray<int> array1(10);for (int i = 0; i < 10; ++i) {array1.push_back(i);}cout << "array1打印輸出:" << endl;printIntArray(array1);cout << "array1的大小:" << array1.getSize() << endl;cout << "array1的容量:" << array1.getCapacity() << endl;cout <<-----------------------------------" << endl;MyArray<int> array2(array1);array2.pop_back();cout << "array2打印輸出:" << endl;printIntArray(array2);cout << "array2的大小:" << array2.getSize() << endl;cout << "array2的容量:" << array2.getCapacity() << endl;
}// 測試自定義數據類型
class Person {
public:Person() {}Person(string name, int age) {this->m_Name = name;this->m_Age = age;}public:string m_Name;int m_Age;
};
void printPersonArray(MyArray<Person>& personArr) {for (int i = 0; i < personArr.getSize(); ++i) {cout << "姓名:" << personArr[i].m_Name << " 年齡:" << personArr[i].m_Age << endl;}
}void test02() {// 創建數組MyArray<Person>pArray(10);Person p1("孫悟空", 999);Person p2("韓信", 20);Person p3("妲己", 18);Person p4("王昭君", 15);Person p5("趙云", 24);// 插入數據pArray.push_back(p1);pArray.push_back(p2);pArray.push_back(p3);pArray.push_back(p4);pArray.push_back(p5);printPersonArray(pArray);cout << "pArray的大小:" << pArray.getSize() << endl;cout << "pArray的容量:" << pArray.getCapacity() << endl;
}int main() {test01();test02();system("pause");return 0;
}

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

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

相關文章

【算法】算法題-20231211

這里寫目錄標題 一、387. 字符串中的第一個唯一字符二、1189. “氣球” 的最大數量三、1221. 分割平衡字符串 一、387. 字符串中的第一個唯一字符 簡單 給定一個字符串 s &#xff0c;找到 它的第一個不重復的字符&#xff0c;并返回它的索引 。如果不存在&#xff0c;則返回…

算法通關村第十五關 | 青銅 | 用4KB內存尋找重復元素

處理海量數據的思路 1.使用位存儲&#xff1a;占用的空間是存整數的 1/8 。 2.分塊&#xff1a;也叫外部排序&#xff0c;將大文件劃分為若干小塊&#xff0c;先處理小塊再逐步得到想要的結果&#xff0c;需要至少遍歷兩次全部序列&#xff0c;是用時間換空間的方法。 3.堆&…

Mockjs 增、刪、改、查(分頁、多條件查詢)

查&#xff08;分頁、多條件查詢&#xff09;&#xff1a; 關鍵代碼&#xff1a; Mock.mock(/vue-table-list/tableLinkage/list, post, (option) > {// console.log("&#x1f680; ~ file: tableLinkage.js:66 ~ Mock.mock ~ option:", option)const params J…

MFC畫折線圖,基于x64系統

由于項目的需要&#xff0c;需要畫一個折線圖。 傳統的Teechart、MSChart、HighSpeedChart一般是只能配置在x86系統下&#xff0c;等到使用x64系統下運行就是會報出不知名的錯誤&#xff0c;這個地方讓人很苦惱。 我在進行配置的過程之中&#xff0c;使用Teechart將x86配置好…

基于Java SSM框架實現班級同學錄、聚會報名網站系統項目【項目源碼+論文說明】

基于java的SSM框架實現班級同學錄聚會報名網站系統演示 摘要 21世紀的今天&#xff0c;隨著社會的不斷發展與進步&#xff0c;人們對于信息科學化的認識&#xff0c;已由低層次向高層次發展&#xff0c;由原來的感性認識向理性認識提高&#xff0c;管理工作的重要性已逐漸被人…

程序員考公筆記之邏輯判斷(圖形推理)

文章目錄 寫在前面1、邏輯判斷1.1、圖形推理1.1.1、位置類1.1.2、樣式類1.1.3、數量類1.1.4、屬性類1.1.5、六面體 寫在前面 1、邏輯判斷 1.1、圖形推理 觀察&#xff1a;先宏觀&#xff0c;再微觀 圖形推理的命題形式&#xff1a; 一組式 觀察路徑&#xff1a;順序看(考最…

解決方案- 材料吸波、屏蔽性能測試系統 (10MHz~500GHz)

材料吸波、屏蔽性能測試系統 &#xff08;10MHz~500GHz&#xff09; 材料電磁參數綜合測試解決方案 材料吸波、屏蔽性能測試系統測試頻率范圍可達10MHz&#xff5e;500GHz&#xff0c;可實現材料反射率、屏蔽性能特性參數測試。系統由矢量網絡分析儀、測試夾具、系統軟件等組…

申論筆記(思路技巧)

文章目錄&#xff1a; 一&#xff1a;福利 二&#xff1a;常見題型 1.歸納概括題 2.提出對策/措施/建議題 2.1 找到對策的來源 2.2 提煉對策 2.3 明確是否需要先概括問題 2.4 對策表述三部曲 3.綜合分析題 3.1 綜合分析最大的難點 3.2 分析問題的技巧 4.應用文/公文…

力扣每日一題day34[110. 平衡二叉樹]

給定一個二叉樹&#xff0c;判斷它是否是高度平衡的二叉樹。 本題中&#xff0c;一棵高度平衡二叉樹定義為&#xff1a; 一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1 。 示例 1&#xff1a; 輸入&#xff1a;root [3,9,20,null,null,15,7] 輸出&#xff1a;t…

wappalyzer基于插件的網站開發技術解析工具

一、wappalyzer 解釋&#xff1a;這是一款強大的工具&#xff0c;其主要能提供一種快速、可靠地檢測網站所使用技術棧的方法&#xff0c;也就說說&#xff0c;服務器發來的信息都會被它剖析&#xff0c;然后分析出前端的技術棧&#xff0c;有時后端所使用的技術棧如果網頁特征…

[ 藍橋杯Web真題 ]-冬奧大抽獎

目錄 介紹 準備 目標 規定 思路 知識補充 解法參考 介紹 藍橋云課慶冬奧需要舉行一次抽獎活動&#xff0c;我們一起做一個頁面提供給云課冬奧抽獎活動使用。 準備 開始答題前&#xff0c;需要先打開本題的項目代碼文件夾&#xff0c;目錄結構如下&#xff1a; ├──…

甲醛處理企業網站效果如何

甲醛往往是新裝房間主所擔心的問題&#xff0c;而甲醛處理公司則可以處理甲醛問題&#xff0c;市場需求也比較高&#xff0c;雖然具備同城服務屬性&#xff0c;但外地或連鎖經營也非常適合&#xff0c;而品牌們也遇到一些痛點&#xff1a; 1、品牌宣傳拓客難 甲醛處理公司也需…

公司app定制開發 ,打造專屬企業移動應用

公司app定制&#xff1a;打造專屬企業移動應用 在當今數字化時代&#xff0c;移動應用已經成為了人們生活中不可或缺的一部分&#xff0c;越來越多的企業也意識到了移動應用對于企業形象和業務拓展的重要性&#xff0c;為了滿足企業的需求&#xff0c;公司app定制服務應運而生…

基于查表法的水流量算法設計與實現

寫在前面 本文分享的是一種基于查表法的水流量的算法方案設計與實現&#xff0c;算法簡單易懂&#xff0c;主要面向初學者&#xff0c;有兩個目的&#xff1a;一是給初學者一些算法設計的思路引導&#xff1b;二是引導初學者學習怎樣用C語言編程實現。 一、設計需求 基于“19…

C++ 中的引用

文章目錄 C 引用的應用1. 修改函數中傳遞的參數2. 避免復制大型結構3. for 循環中修改所有對象4. for 循環中避免復制對象 References vs Pointers引用的限制使用引用的優點練習Quesition 1Question 2Question 3Question 4Question 5Question 6 如果一個變量被聲明為引用&#…

Android-Framework 默認橫屏、dpi設置

一、環境 高通865 Android 10 二、源碼修改位置 1、修改dpi device/qcom/kona/kona.mk -116,7 116,7 TARGET_USES_RRO : true# system prop for Bluetooth SOC typePRODUCT_PROPERTY_OVERRIDES \vendor.qcom.bluetooth.sochastings \ - ro.sf.lcd_density480ro.sf.lcd_d…

Python中的logging介紹

Python中的logging模塊是一個強大的、靈活的、可配置的日志記錄系統。它允許你在不修改源代碼的情況下記錄錯誤和調試信息&#xff0c;同時也可以對日志信息進行各種處理&#xff0c;例如寫入到文件、輸出到控制臺、記錄到數據庫等。 logging模塊提供了一種用于日志記錄的通用接…

液態二氧化碳儲存罐遠程無線監測系統

二氧化碳強化石油開采技術&#xff0c;須先深入了解石油儲層的地質特征和二氧化碳的作用機制。現場有8輛二氧化碳罐裝車&#xff0c;每輛罐車上有4臺液態二氧化碳儲罐&#xff0c;每臺罐的尾部都裝有一臺西門子S7-200 smart PLC。在注入二氧化碳的過程中&#xff0c;中控室S7-1…

國產單片機XL32F001,價格便宜,性價比高,32位M0+內核

XL32F001芯片簡介 1、是一個32位ARM架構Cortex -M0系列的單片機 2、系統工作頻率最高為24MHz 3、擁有24Kbytes Flash存儲器和3Kbytes SRAM 4、擁有內部24MHz和32.768MHz的RC振蕩器&#xff08;HSI和LSI&#xff09;&#xff0c;擁有32.768KHz低速晶體振蕩器&#xff08;LSE…

JVM內存模型+JVM類加載機制

jvm內存模型包括哪些以及各自作用 主要包括類加載 對象創建 方法調用 本地方法區 程序計數 方法區&#xff1a; class文件加載到方法區 堆&#xff1a; 對象創建在堆內存中 jvm棧&#xff1a;方法調用入棧 本地方法棧&#xff1a;主要是c寫的一些方法 程序計數器&#xff1a;存…