【C++】泛型編程 ? ( 類模板示例 - 數組類模板 | 自定義類中持有指針成員變量 )

文章目錄

  • 一、支持 數組類模板 存儲的 自定義類
    • 1、可拷貝和可打印的自定義類
    • 2、改進方向
    • 3、改進方向 - 構造函數
    • 4、改進方向 - 析構函數
    • 5、改進方向 - 重載左移運算符
    • 6、改進方向 - 重載拷貝構造函數 和 等號運算符
  • 二、代碼示例
    • 1、Array.h 頭文件
    • 2、Array.cpp 代碼文件
    • 3、Test.cpp 主函數代碼文件
    • 4、Test.cpp 主函數代碼文件






一、支持 數組類模板 存儲的 自定義類




1、可拷貝和可打印的自定義類


在上一篇博客 中 , 定義了 可拷貝 與 可打印 的 自定義類 Student , 可以被存放到 數組類模板 中 ;

由于其 成員變量 char m_name[32] 是 數組類型 , 創建時就直接分配了內存空間 , 即使淺拷貝也可以完成對 該類型對象的 拷貝工作 ;

class Student
{friend ostream& operator<<(ostream& out, const Student& s);
public:Student(){m_age = 10;strcpy(m_name, "NULL");}Student(const char* name, int age) {strcpy(this->m_name, name);this->m_age = age;}void printT() {cout << "name : " << m_name << " , age : " << m_age << endl;}private:char m_name[32];int m_age;
};// 重載左移運算符實現
ostream& operator<<(ostream& out, const Student& s) {out << "name : " << s.m_name << " , age : " << s.m_age << " ; ";return out;
}

2、改進方向


本篇博客中 , 開始討論 自定義類 中是 char* 類型指針的情況 , 這里涉及到了 堆內存分配 以及 深拷貝 問題 ;


如果將上述 Student 類中的 char m_name[32] 數組成員 , 改為 char* m_name 指針成員 ;


那么需要進行 堆內存管理 ,

  • 在 構造函數中 分配堆內存 ;
  • 在 析構函數中 釋放堆內存 ;

為了避免 淺拷貝 問題出現 , 需要

  • 進行 等號 = 運算符重載 ;
  • 以及 重寫 拷貝構造函數 ;

為了使用 cout 打印該 類對象 , 需要 進行 左移 << 運算符重載 ;


3、改進方向 - 構造函數


在類的 無參構造函數 和 有參構造函數中 ,

使用 new 關鍵字 , 自動在堆內存中分配內存 , 然后為 堆內存 中的空間賦值 ;

	Student(){m_age = 10;// 創建一個數組個數為 1 的數組, 存放 '\0' 值// 這是一個空字符串m_name = new char[1];strcpy(m_name, "");}Student(const char* name, int age) {// 計算字符串大小// 總的大小是 字符個數 + \0 字符, 因此多一個字節int len = strlen(name) + 1;// 根據字符串大小創建 字符數組m_name = new char[len];strcpy(this->m_name, name);this->m_age = age;}

4、改進方向 - 析構函數


在析構函數中 , 需要將 使用 new 關鍵字申請的 堆內存進行釋放 , 這里必須使用 delete 進行釋放 ;

使用 malloc 申請的堆內存 , 必須使用 free 進行釋放 ;

使用 new 申請的堆內存 , 必須使用 delete 進行釋放 ;

	~Student(){if (m_name != NULL){delete[] m_name;m_name = NULL;}}

5、改進方向 - 重載左移運算符


重載左移運算符 , 以便可以在 cout 中打印該類信息 ;

首先 , 在類內部聲明 重載左移運算符 的友元函數 ;

class Student
{friend ostream& operator<<(ostream& out, const Student& s);
}

然后 , 在 類外部 的 全局函數 中 , 實現 重載左移運算符函數 ;

// 重載左移運算符實現
ostream& operator<<(ostream& out, const Student& s) {out << "name : " << s.m_name << " , age : " << s.m_age << " ; ";return out;
}

6、改進方向 - 重載拷貝構造函數 和 等號運算符


重載拷貝構造函數 和 等號運算符 , 方便類初始化 和 使用等號賦值 ;

	Student(const Student& s) {// 計算字符串大小// 總的大小是 字符個數 + \0 字符, 因此多一個字節int len = strlen(s.m_name) + 1;// 根據字符串大小創建 字符數組m_name = new char[len];strcpy(this->m_name, s.m_name);this->m_age = s.m_age;}// 重載等號操作符Student& operator=(const Student& obj) {if (m_name != NULL) {delete[] m_name;m_name = NULL;}// 計算字符個數int len = strlen(obj.m_name) + 1;// 根據字符串大小創建 字符數組m_name = new char[len];strcpy(this->m_name, obj.m_name);this->m_age = obj.m_age;return *this;}




二、代碼示例




1、Array.h 頭文件


#pragma once#include "iostream"
using namespace std;template <typename T>
class Array
{// 左移 << 操作符重載// 注意 聲明時 , 需要在 函數名 和 參數列表之間 注明 泛型類型 <T>//		實現時 , 不能在 函數名 和 參數列表之間 注明 泛型類型 <T>friend ostream& operator<< <T> (ostream& out, const Array& a);public:// 有參構造函數Array(int len = 0);// 拷貝構造函數Array(const Array& array);// 析構函數~Array();public:// 數組下標 [] 操作符重載// 數組元素類型是 T 類型T& operator[](int i);// 等號 = 操作符重載Array& operator=(const Array& a);private:// 數組長度int m_length;// 指向數組數據內存 的指針// 指針類型 是 泛型類型 TT* m_space;
};

2、Array.cpp 代碼文件


#include "Array.h"// 左移 << 操作符重載
// 注意 聲明時 , 需要在 函數名 和 參數列表之間 注明 泛型類型 <T>
//		實現時 , 不能在 函數名 和 參數列表之間 注明 泛型類型 <T>
template <typename T>
ostream& operator<< (ostream& out, const Array<T>& a)
{for (int i = 0; i < a.m_length; i++){// 在一行內輸入數據, 使用空格隔開, 不換行out << a.m_space[i] << " ";}// 換行out << endl;return out;
}// 有參構造函數
template <typename T>
Array<T>::Array(int len)
{// 設置數組長度m_length = len;// 為數組在堆內存中分配內存// 注意 元素類型為 Tm_space = new T[m_length];cout << " 調用有參構造函數 " << endl;
}// 拷貝構造函數
// 這是一個深拷貝 拷貝構造函數
template <typename T>
Array<T>::Array(const Array<T>& array)
{// 設置數組長度m_length = array.m_length;// 創建數組// 注意 元素類型為 Tm_space = new T[m_length];// 為數組賦值for (int i = 0; i < m_length; i++){m_space[i] = array.m_space[i];}cout << " 調用拷貝構造函數 " << endl;
}// 析構函數
template <typename T>
Array<T>::~Array()
{if (m_space != NULL){// 釋放 new T[m_length] 分配的內存 delete[] m_space;m_space = NULL;m_length = 0;}cout << " 調用析構函數 " << endl;
}// 數組下標 [] 操作符重載
template <typename T>
T& Array<T>::operator[](int i)
{return m_space[i];
}// 等號 = 操作符重載
template <typename T>
Array<T>& Array<T>::operator=(const Array<T>& a)
{if (this->m_space != NULL){// 釋放 new int[m_length] 分配的內存 delete[] this->m_space;this->m_space = NULL;}// 設置數組長度this->m_length = a.m_length;// 創建數組this->m_space = new T[m_length];// 為數組賦值for (int i = 0; i < m_length; i++){this->m_space[i] = a.m_space[i];}cout << " 調用 等號 = 操作符重載 函數" << endl;// 返回是引用類型// 返回引用就是返回本身// 將 this 指針解引用, 即可獲取數組本身return *this;
}

3、Test.cpp 主函數代碼文件


#define _CRT_SECURE_NO_WARNINGS
#include "iostream"
using namespace std; // 此處注意, 類模板 聲明與實現 分開編寫
// 由于有 二次編譯 導致 導入 .h 頭文件 類模板函數聲明 無法找到 函數實現
// 必須 導入 cpp 文件
#include "Array.cpp"class Student
{friend ostream& operator<<(ostream& out, const Student& s);
public:Student(){m_age = 10;// 創建一個數組個數為 1 的數組, 存放 '\0' 值// 這是一個空字符串m_name = new char[1];strcpy(m_name, "");}Student(const char* name, int age) {// 計算字符串大小// 總的大小是 字符個數 + \0 字符, 因此多一個字節int len = strlen(name) + 1;// 根據字符串大小創建 字符數組m_name = new char[len];strcpy(this->m_name, name);this->m_age = age;}Student(const Student& s) {// 計算字符串大小// 總的大小是 字符個數 + \0 字符, 因此多一個字節int len = strlen(s.m_name) + 1;// 根據字符串大小創建 字符數組m_name = new char[len];strcpy(this->m_name, s.m_name);this->m_age = s.m_age;}void printT() {cout << "name : " << m_name << " , age : " << m_age << endl;}~Student(){if (m_name != NULL){delete[] m_name;m_name = NULL;}}// 重載等號操作符Student& operator=(const Student& obj) {if (m_name != NULL) {delete[] m_name;m_name = NULL;}// 計算字符個數int len = strlen(obj.m_name) + 1;// 根據字符串大小創建 字符數組m_name = new char[len];strcpy(this->m_name, obj.m_name);this->m_age = obj.m_age;return *this;}private:char* m_name;int m_age;
};// 重載左移運算符實現
ostream& operator<<(ostream& out, const Student& s) {out << "name : " << s.m_name << " , age : " << s.m_age << " ; ";return out;
}int main() {// 驗證 有參構造函數Array<Student> array(3);Student s0("Tom", 18), s1("Jerry", 12), s2("Jack", 16);array[0] = s0;array[1] = s1;array[2] = s2;// 遍歷數組 打印數組元素for (int i = 0; i < 3; i++) {array[i].printT();}cout << array << endl;// 控制臺暫停 , 按任意鍵繼續向后執行system("pause");return 0;
}

4、Test.cpp 主函數代碼文件


執行結果 :

調用有參構造函數
name : Tom , age : 18
name : Jerry , age : 12
name : Jack , age : 16
name : Tom , age : 18 ; name : Jerry , age : 12 ; name : Jack , age : 16 ;

Press any key to continue . . .

在這里插入圖片描述

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

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

相關文章

[網鼎杯 2020 朱雀組]phpweb

看一下源碼 應該是輸入的date 作為函數&#xff0c;value作為內部參數的值&#xff0c;將date()函數返回的結果顯示在頁面上 回去看的時候&#xff0c;意外發現頁面有了新的跳轉&#xff0c;觀察一下發現&#xff0c;頁面每隔五秒就會發生一次跳轉 所以就抓包看看 抓包發現po…

GEE:kNN(k-最近鄰)分類教程(樣本制作、特征添加、訓練、精度、最優參數、統計面積)

作者:CSDN @ _養樂多_ 本文將介紹在Google Earth Engine (GEE)平臺上進行kNN(k-最近鄰)分類的方法和代碼,其中包括制作樣本點教程(本地、在線和本地在線混合制作樣本點,合并樣本點等),加入特征變量(各種指數、紋理特征、時間序列特征、物候特征等),運行kNN(k-最近…

Linux中,查看Tomcat版本、如何查看Tomcat版本

方法 在tomcat的bin目錄下&#xff0c;執行version.sh命令即可 結果

python每日一題——3最長連續序列

題目 給定一個未排序的整數數組 nums &#xff0c;找出數字連續的最長序列&#xff08;不要求序列元素在原數組中連續&#xff09;的長度。 請你設計并實現時間復雜度為 O(n) 的算法解決此問題。 示例 1&#xff1a; 輸入&#xff1a;nums [100,4,200,1,3,2] 輸出&#xf…

RpcServiceContext上下文

消費者: web 提供者: buss-service 同一服務器: 192.168.100.228 RpcServiceContext serviceContext RpcContext.getServiceContext(); //web->buss-serviceLOGGER.warn("getRequest->{}", JsonUtil.toJson(serviceContext.getRequest())); //getRequest-…

ElementUI table+dialog實現一個簡單的可編輯的表格

table組件如何實現可編輯呢&#xff1f; 我的需求是把table組件那樣的表格&#xff0c;實現它點擊可以彈出一個框&#xff0c;然后在這個框里面輸入你的東西&#xff0c;然后將他回顯回去&#xff0c;當然&#xff0c;輸入的有可能是時間啥的。 為什么要彈出彈層不在框上直接…

最近iphone手機的交管12123閃退,打不開的解決辦法?

蘋果手機系統和新版軟件不配&#xff0c;終極決絕辦法&#xff1a;升級IOS系統就好 可能是手機的內存不足了&#xff0c;因為在使用APP時&#xff0c;需要占用手機的內存&#xff0c;如果手機內存不足以支持軟件允許&#xff0c;軟件就會閃退。車主可以清理一下手機的內存&…

彈窗msvcp140_1.dll丟失的解決方法,超簡單的方法分享

在計算機使用過程中&#xff0c;我們經常會遇到一些錯誤提示&#xff0c;其中最常見的就是缺少某個文件的錯誤。最近&#xff0c;我在使用某些軟件時&#xff0c;遇到了一個名為“msvcp140_1.dll”的錯誤提示。這個錯誤通常出現在運行某些程序時&#xff0c;由于缺少了msvcp140…

項目總結報告(案例模板)

軟件項目總結報告模板套用&#xff1a; 項目概要項目工作分析經驗與教訓改進建議可納入的項目過程資產 --------進主頁獲取更多資料-------

2023年【汽車駕駛員(中級)】最新解析及汽車駕駛員(中級)試題及解析

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 2023年汽車駕駛員&#xff08;中級&#xff09;最新解析為正在備考汽車駕駛員&#xff08;中級&#xff09;操作證的學員準備的理論考試專題&#xff0c;每個月更新的汽車駕駛員&#xff08;中級&#xff09;試題及解…

Doris中的物化視圖-查詢(十九)

物化視圖創建完成后&#xff0c;用戶的查詢會根據規則自動匹配到最優的物化視圖。 比如我們有一張銷售記錄明細表&#xff0c;并且在這個明細表上創建了三張物化視圖。一個存儲了不同時間不同銷售員的售賣量&#xff0c;一個存儲了不同時間不同門店的銷售量&#xff0c;以及每…

C#,《小白學程序》第二課:數組,循環與排序

1 什么是數組&#xff1f; 數組 Array 是一組數值&#xff08;數 或 值&#xff09;。 int[] a; int[,] b; int[][] c; Anything[] d; 都是數組。 2 排序 排序就是按大小、名字、拼音或你指定的信息進行比較后排隊。 排序是數組最基本的功能需求。 3 文本格式 /// <summa…

《數據結構、算法與應用C++語言描述》-代碼實現散列表(線性探查與鏈式散列)

散列表 完整可編譯運行代碼&#xff1a;Github:Data-Structures-Algorithms-and-Applications/_22hash/ 定義 字典的另一種表示方法是散列&#xff08;hashing&#xff09;。它用一個散列函數&#xff08;也稱哈希函數&#xff09;把字典的數對映射到一個散列表&#xff08…

spring-webflux的一些概念的理解

Spring5的webflux可以支持高吞吐量&#xff0c;使用相同的資源可以處理更加多的請求&#xff0c;它將會成為未來技術的趨勢&#xff0c;但是相對于學習其他的框架相比&#xff0c;它的學習曲線很高&#xff0c;綜合了很多現有的技術&#xff0c;即使按照教程學習能編寫代碼&…

requests庫的學習(詳細篇)

一、request庫的安裝 requests屬于第三方庫&#xff0c;Python不內置&#xff0c;因此需要我們手動安裝。 pip3 install requests

HTML5新特性

HTML5新特性 前言語義化標簽常用語義化標簽優點 新增input屬性新增type屬性值內容其他新增input屬性 video&#xff08;視頻&#xff09;與audio&#xff08;音頻&#xff09;標簽 前言 本文主要講解HTML5中新增了哪些內容。 語義化標簽 HTML5新增了語義化標簽這個特性&…

第一類曲線積分@對弧長的曲線積分

文章目錄 abstract對弧長的曲線積分曲線形構件的質量第一類曲線積分曲線積分存在性利用曲線積分的定義描述曲線形構件質量問題推廣曲線積分可加性閉曲線積分 曲線積分性質曲線積分的計算方法證明(部分推導) 小結曲線弧顯函數形式方程下的曲線積分公式推廣例例例 abstract 在積…

html table樣式的設計 表格邊框修飾

<!DOCTYPE html> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> <title>今日小說排行榜</title> <style> table {border-collapse: collapse;border: 4px double red; /*…

Python之Pygame游戲編程詳解

一、介紹 1.1 定義 Pygame是一種流行的Python游戲開發庫&#xff0c;它提供了許多功能&#xff0c;使開發人員可以輕松創建2D游戲。它具有良好的跨平臺支持&#xff0c;可以在多個操作系統上運行&#xff0c;例如Windows&#xff0c;MacOS和Linux。在本文中&#xff0c;我們將…

單鏈表的反轉?太細了哥們!細到離譜!

單鏈表的反轉&#xff08;面試常出&#xff09;&#xff1a; ? 單鏈表的反轉&#xff0c;可以通過很多種方法實現。包括迭代法&#xff0c;遞歸法&#xff0c; 迭代法&#xff1a; 定義三個指針&#xff1a;prev、current和next&#xff0c;它們分別表示前一個節點、當前節點…