C++提高編—(模板,泛型,異常處理)

一 模板

1.1 模板概論

以下圖為例子,提供了三個西裝的證件照,誰都可以取拍照,可以是小孩,男女人,也可以是某些動物等等等。n那么我們這個模板也是這樣,它可以是任何類型,基礎類型,class型,等等等等。且會根據你的指定類型編程相對類型(配對)

模板的特點:

  • 模板不可以直接使用,它只是一個框架

  • 模板的通用并不是萬能的

1.2 函數模板

1.2.1 函數模板概念及應用

語法:

template<typename T>
//函數聲明或定義

解釋:

template --- 聲明創建模板

typename --- 表面其后面的符號是一種數據類型,可以用class代替

T --- 通用的數據類型,名稱可以替換,通常為大寫字母

代碼示例:

此定義了兩個int的變量賦值成功了,這時的T就成為了int類型的

#include <iostream>
using namespace std;template <typename T>
int test(T &a, T &b)
{return a + b;
}int main(int argc, char const *argv[])
{// 原代碼傳遞的是臨時常量,而函數模板參數是引用,需要傳遞變量int num1 = 1;int num2 = 2;// test(num1, num2);// 原函數模板要求兩個參數類型一致,這里將 num2 轉換為 int 類型以匹配參數列表cout << test(num1, num2) << endl;return 0;
}

?注意事項:

函數模板 會編譯兩次

第一次:是對函數模板本身編譯

第二次:函數調用處將T的類型具體化

函數模板目標:模板是為了實現泛型,可以減輕編程的工作量,提高函數的重用性

1.2.2 函數模板重載

重載,即在同一作用域下,函數名相同,類型or參數什么的不同。

// 函數模板重載
template <typename T>
void printer(T a, T b)
{cout << "a=" << a << "  b=" << b << endl;cout << "2個參數函數模板執行" << endl;
}
// 這樣重新聲明模板類型T,因為一次聲明只對當前函數生效
template <typename T>
void printer(T a)
{cout << "a=" << a << endl;cout << "1個參數函數模板執行" << endl;
}
int main()
{int a = 10;int b = 20;printer(a);printer(a,b);
}

1.2.3 函數模板與普通函數區別

  • 普通函數調用時可以發生自動類型轉換(隱式類型轉換)

  • 函數模板調用時,如果利用自動類型推導,不會發生隱式類型轉換

  • 如果利用顯示指定類型的方式,可以發生隱式類型轉換

  • 總結:建議使用顯示指定類型的方式,調用函數模板,因為可以自己確定通用類型T

#include <iostream>
using namespace std;// 普通函數
int myAdd01(int a, int b)
{return a + b;
}// 函數模板
template <class T>
T myAdd02(T a, T b)
{return a + b;
}// 使用函數模板時,如果用自動類型推導,不會發生自動類型轉換,即隱式類型轉換
void test01()
{int a = 10;int b = 20;char c = 'c';cout << myAdd01(a, c) << endl; // 正確,將char類型的'c'隱式轉換為int類型  'c' 對應 ASCII碼 99// myAdd02(a, c); // 報錯,使用自動類型推導時,不會發生隱式類型轉換myAdd02<int>(a, c); // 正確,如果用顯示指定類型,可以發生隱式類型轉換
}int main(int argc, char const *argv[])
{test01();system("pause");return 0;
}

1.3 類模板

1.3.1 類模板基本概念

類模板作用:

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

語法:

template<typename T>
//類

解釋:

template --- 聲明創建模板

typename --- 表面其后面的符號是一種數據類型,可以用class代替

T --- 通用的數據類型,名稱可以替換,通常為大寫字母

示例:

#include <iostream>
using namespace std;// 函數模板
template <class Name, class Age>
class demo
{
public:demo(Name name, Age age){this.name = name;this.age = age;}~demo();
};int main(int argc, char const *argv[])
{system("pause");return 0;
}

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

1.3.3?類模板做函數參數

學習目標:

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

一共有三種傳入方式:

  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();std::string typeName1 = "未知類型";std::string typeName2 = "未知類型";if (typeid(T1) == typeid(std::string)){typeName1 = "std::string";}if (typeid(T2) == typeid(int)){typeName2 = "int";}cout << "T1的類型為: " << typeName1 << endl;cout << "T2的類型為: " << typeName2 << endl;
}
void test02()
{Person<string, int> p("豬八戒", 90);printPerson2(p);
}// 3、整個類模板化
template <class T>
void printPerson3(T &p)
{std::string typeName = "未知類型";if (typeid(T) == typeid(Person<std::string, int>)){typeName = "Person<std::string, int>";}cout << "T的類型為: " << typeName << endl;p.showPerson();
}
void test03()
{Person<string, int> p("唐僧", 30);printPerson3(p);
}int main()
{test01();test02();test03();system("pause");return 0;
}

1.3.4?類模板與繼承

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

  • 當子類繼承的父類是一個類模板時,子類在聲明的時候,要指定出父類中T的類型

  • 如果不指定,編譯器無法給子類分配內存

  • 如果想靈活指定出父類中T的類型,子類也需變為類模板

1.3.4.1 普通類繼承
#include <iostream>
#include <string>
using namespace std;
// 父類模板
template <class T>
class Base
{T m;
};// class Son:public Base  //錯誤,c++編譯需要給子類分配內存,必須知道父類中T的類型才可以向下繼承
class Son : public Base<int> // 必須指定一個類型
{
};
void test01()
{Son c;
}// 類模板繼承類模板 ,可以用T2指定父類中的T類型
template <class T1, class T2>
class Son2 : public Base<T2>
{
public:Son2(){cout << typeid(T1).name() << endl;cout << typeid(T2).name() << endl;}
};void test02()
{Son2<int, char> child1;
}int main()
{test01();test02();system("pause");return 0;
}

1.3.6 類模板頭文件和源文件分離問題

學習目標:

  • 掌握類模板成員函數分文件編寫產生的問題以及解決方式

問題:

  • 類模板中成員函數創建時機是在調用階段,導致分文件編寫時鏈接不到

解決:

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

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

推薦寫hpp文件

#pragma once
#include <iostream>
using namespace std;
#include <string>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;

1.3.7 友元類模板

直接舉例說明,不做過多描述

template <class T1,class T2>
class Demo1
{template <class T3, class T4> friend void test1(Demo1<T3, T4> obj);
private:T1 a;T2 b;
public:Demo1(T1 a, T2 b){this->a = a;this->b = b;}
};
// 全局函數模板
template <class T3, class T4>
void test1(Demo1<T3, T4> obj)
{cout << obj.a << "  " << obj.b << endl;
}
1.3.7.1?全局函數模板作為類模板的友元
template <class T1,class T2>
class Demo1
{template <class T3, class T4> friend void test1(Demo1<T3, T4> obj);
private:T1 a;T2 b;
public:Demo1(T1 a, T2 b){this->a = a;this->b = b;}
};
// 全局函數模板
template <class T3, class T4>
void test1(Demo1<T3, T4> obj)
{cout << obj.a << "  " << obj.b << endl;
}
1.3.7.2?類中成員函數作為類模板的友元
template <class T1, class T2>
class Demo1;class Demo2
{
public:template<class T5, class T6>void test2(Demo1<T5, T6> obj){cout << "類中函數模板打印:" << obj.a << "  " << obj.b << endl;}
};template <class T1,class T2>
class Demo1
{template<class T5, class T6> friend void Demo2::test2(Demo1<T5, T6> obj);
private:T1 a;T2 b;
public:Demo1(T1 a, T2 b){this->a = a;this->b = b;}
};
1.3.7.3?普通函數作為類模板的友元
template <class T1,class T2>
class Demo1
{friend void test2(Demo1<int, int> obj);
private:T1 a;T2 b;
public:Demo1(T1 a, T2 b){this->a = a;this->b = b;}
};void test2(Demo1<int,int> obj)
{cout << "普通全局函數打印:" <<  obj.a << "  " << obj.b << endl;
}

1.4 綜合練習

設計一個數組模板類(MyArray),完成對不同類型元素的管理。不僅能操作基本數據類型,還可以操作自定義數據類型

還是一個動態數組,可以擴容等操作

二 泛型(與Java對比)?

詳述在之前寫的文章,感興趣的同學們,可以去看看。

zz?????????????Java 自定義異常(案例)throws與throw的區別_throw的例子分數不合法-CSDN博客

Java 異常處理之Throwable的常用成員方法的概述_throwable getmessage get detail-CSDN博客

Java 自定義異常(案例)throws與throw的區別_throw的例子分數不合法-CSDN博客

三 異常處理

3.1 基本語法

// 寫一個計算兩個數相除的算法
int division(int a, int b)
{if (b == 0){// 對于函數的返回值是可以忽略的,但是異常不可以//return -1;	// -1表示參數有問題throw - 1;	// 拋出異常,throw是關鍵字,-1是異常值,異常值可以隨便寫// 如果拋出異常,不會返回-1,而是該函數直接在這個地方結束,進入到catch}return a / b;	// 否則就返回正常的除法結果
}
void fun1()
{int a = 10;int b = 0;// 拋出異常,就要捕獲異常,否則程序將直接崩潰int res;try{// 把會拋出異常的語句放到try中res = division(a, b);}catch (int e)// 異常值類型 異常值{//并要在catch中處理捕獲到異常以后要做的事情res = 0;cerr << "int類型異常" << endl;}// 當然也可以寫多個catch塊catch (char e){res = 0;cerr << "char類型異常" << endl;}catch (...)	// 捕獲其他所有類型異常{res = 0;cerr << "其他類型異常" << endl;}int res1 = res * 100;cout << "(10/0)*100=" << res1 << endl;
}

3.2 棧解旋(unwinding)

從進入 try 塊起,到異常被拋擲前,這期間在棧上構造的所有對象,都會被自動析構。析構的順序與構造的順序相反,這一過程稱為棧的解旋(unwinding).

class Demo
{
public:int a;
public:Demo(){cout << "無參構造" << endl;}Demo(int a){this->a = a;cout << "有參構造;a=" << this->a << endl;}~Demo(){cout << "析構函數;a=" << this->a << endl;}
};void fun1()
{try{Demo ob1(10);Demo ob2(20);Demo ob3(30);// 拋出異常時,當前程序就會自動進入catch處理異常,因此要將局部變量 ob3 ob2 ob1依次釋放throw 1;}catch (int){cout << "int類型異常" << endl;}catch (...){cout << "其他類型異常" << endl;}}

2.3 函數不能拋出異常- 了解


// 使用 noexcept 規格來指定函數是否可以拋出異常
// 該函數不允許拋出異常
void test04()noexcept(true)
{throw 1;
}
// 該函數可以拋出異常
void test05()noexcept(false)
{throw 1;
}
void fun1()
{try{test05();}catch (int){cout << "int類型異常" << endl;}catch (char){cout << "char類型異常" << endl;}catch (const char *){cout << "const char *類型異常" << endl;}catch (float){cout << "float類型異常" << endl;}catch (...){cout << "其他類型異常" << endl;}
}

異常接口說明在不同的編譯器,編譯結果是不一樣的。

3.4 異常的多態使用

// 定義一個基本的父類異常類
class BaseException
{
public:virtual void printExceptionMsg() {};
};
// 定義一個空指針異常,繼承于BaseException
class NullPointerException :public BaseException
{
public:void printExceptionMsg(){cout << "null pointer exception!" << endl;}
};
// 定義一個數組下標越界異常,繼承于BaseException
class IndexOutOfException :public BaseException
{
public:void printExceptionMsg(){cout << " Index out of range!" << endl;}
};
void fun1()
{try{throw IndexOutOfException();}// 如果要處理多種異常,沒必要在這個地方寫N多個catch// 讓它們繼承于同一個父類,然后在這個地方用父類引用接收不同子類對象就可以// 這就是之前講過的多態catch (BaseException &e){e.printExceptionMsg();}
}

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

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

相關文章

Python圖像處理基礎(六)

Python圖像處理基礎(六) 文章目錄 Python圖像處理基礎(六)3.4 雙層圖像3.5 具有更多色階的位圖數據3.6 基于調色板的圖像3.6.1 超過 256 種顏色的圖像3.7 處理透明度3.7.1 Alpha 通道3.7.2 透明調色板條目3.7.3 透明顏色3.8 隔行掃描和交替像素排序3.4 雙層圖像 某些類型的…

卷積神經網絡(一)

第七章 卷積神經網絡 從今天開始學習卷積神經網絡的內容。 本章的主題是卷積神經網絡&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;。 CNN被用于圖像識別、語音識別等各種場合&#xff0c;在圖像識別的比賽中&#xff0c;基于 深度學習的方法幾乎都以…

OpenCV 多邊形繪制與填充

一、知識點 1、void polylines(InputOutputArray img, InputArrayOfArrays pts, bool isClosed, const Scalar & color, int thickness 1, int lineType LINE_8, int shift 0 ); (1)、在圖像上繪制多邊形曲線。 (2)、參數說明: img: 輸入、輸出參數&#xff0…

C#接口代碼記錄

using System;namespace InterfacesExample {// 定義接口public interface INBAPlayable{void KouLan();}public interface ISupermanable{void Fly();}// 基類public class Person{public void CHLSS(){Console.WriteLine("人類吃喝拉撒睡");}}// Student 類實現多個…

SpringDataJpa實體類中屬性順序與數據庫中生成字段順序不一致的問題

自己寫的代碼覆蓋hibernate中的代碼 翻了翻源碼發現&#xff0c;很多地方都是使用LinkedHashMap或者是List來傳輸Entity里面的fields&#xff0c;于是感覺Hibernate應該是考慮到使用Entity里面定義的fields的順序來實現建表語句里的表字段順序的。   于是就一步步跟蹤下去&…

軟件架構期末復習

題型 填空題 20分,2分/空,10空 選擇題 30分,2分/題,15題 簡答題 30分,6分/題,5題(概念+分析) 案例分析題 20分,5個小題(綜合) 分值:體系結構、設計模式各占50% 考試內容 體系結構 SA基礎(SA03PPT):SA概念、SA與軟件過程(階段)的關系、SA核心概念模型(重要…

Oracle ADG 日常巡檢指南

一、基礎狀態檢查 數據庫角色與模式 SELECT db_unique_name, open_mode, database_role, switchover_status FROM v$database;預期狀態&#xff1a; 主庫&#xff1a;OPEN_MODEREAD WRITE, DATABASE_ROLEPRIMARY備庫&#xff1a;OPEN_MODEREAD ONLY WITH APPLY, DATABASE_ROLE…

【MV】key_moments 與 continuous_timeline的編排權衡

一、編排順序: key_moments → continuous_timeline* 建議使用順序:key_moments → continuous_timeline ?? 兩者關系 key_moments:從continuous_timeline中精選出來的重點(約11個關鍵時間點)continuous_timeline:完整的時間軸(37個片段,覆蓋每句歌詞)?? 實際編…

Tomcat線程模型

目錄 1 Linux I/O模型 2 Linux I/O模型分類 3 Tomcat支持的I/O模型 4 Tomcat I/O模型選型 5 Tomcat NIO實現 6 Tomcat異步IO實現 1 Linux I/O模型 I/O&#xff1a;在計算機內存和外部設備之間拷貝數據的過程程序通過cpu向外部設備發出讀指令&#xff0c;數據從外部設置拷貝至內…

最新Spring Security實戰教程企業級安全方案設計實現

最新Spring Security實戰教程&#xff08;十七&#xff09;企業級安全方案設計 - 多因素認證&#xff08;MFA&#xff09;實現 1. 前言2. 為什么需要多因素認證&#xff1f; 傳統認證的風險MFA的核心優勢常見多因素認證實現方案 3. 多因素認證的核心原理4. 系統架構與流程設計…

十九、【用戶管理與權限 - 篇一】后端基礎:用戶列表與角色模型的初步構建

【用戶管理與權限 - 篇一】后端基礎:用戶列表與角色模型的初步構建 前言準備工作第一部分:回顧 Django 內置的 `User` 模型第二部分:設計并創建 `Role` 和 `UserProfile` 模型第三部分:創建 Serializers第四部分:創建 ViewSets第五部分:注冊 API 路由第六部分:后端初步測…

大話軟工筆記—架構的概要設計

架構的概要設計是在需求工程分析成果的基礎之上對整個系統進行的頂層規劃&#xff0c;重點是確定設計規范&#xff08;理念、主線等&#xff09;&#xff0c;從大的范圍和高度對業務進行規劃和設計&#xff0c;架構概要設計的成果“業務架構圖”&#xff0c;是后續各階段設計的…

Flink CDC —部署模式

一、Standalone 模式 獨立模式是Flink最簡單的部署模式。本簡短指南將向您展示如何下載最新穩定版本的Flink&#xff0c;安裝和運行它。 您還將運行一個示例Flink CDC作業&#xff0c;并在web UI中查看它。 1、準備 Flink在所有類似UNIX的環境中運行&#xff0c;即Linux、Mac…

day029-Shell自動化編程-計算與while循環

文章目錄 1. read 交互式初始化變量1.1 案例-安裝不同的軟件1.2 案例-比較大小 2. 計算2.1 bc2.2 awk2.3 expr2.4 let2.5 案例-計算內存的空閑率2.6 案例-檢查域名過期時間和https證書過期時間 3. 循環3.1 循環控制語句3.2 for循環-c語言格式3.3 while循環3.3.1 案例-猜數字3.3…

華為云Flexus+DeepSeek征文 | 基于華為云ModelArts Studio打造AingDesk AI聊天助手

華為云FlexusDeepSeek征文 | 基于華為云ModelArts Studio打造AingDesk AI聊天助手 引言一、ModelArts Studio平臺介紹華為云ModelArts Studio簡介ModelArts Studio主要特點 二、安裝AingDesk應用AingDesk應用介紹下載地址安裝AingDesk工具 三、開通DeepSeek-R1-0528商用服務訪問…

深度解析Git錯誤:`fatal: detected dubious ownership in repository` 的根源與解決方案

如果你是在使用自己的移動硬盤&#xff08;U盤&#xff09;操作項目時遇到的這個問題直接執行git config --global --add safe.directory X:/path即可&#xff0c;只要你的移動硬盤&#xff08;U盤&#xff09;沒有病毒就不會有安全問題。 深度解析Git錯誤&#xff1a;fatal: d…

基于Spring Boot的校園社區平臺設計與實現

目錄 一.&#x1f981;前言二.&#x1f981;開源代碼與組件使用情況說明三.&#x1f981;核心功能1. ?算法設計2. ?Thymeleaf模板引擎3. ?MyBatis Plus框架4. ?部署項目 四.&#x1f981;演示效果1. 管理員模塊1.1 用戶管理1.2 瀏覽管理員首頁1.3 論壇管理1.4 校園咨詢管理…

Java 8 Map 新增方法詳解

Java 8 Map 新增方法詳解 1. getOrDefault 源碼&#xff1a; default V getOrDefault(Object key, V defaultValue) {V v;return (((v get(key)) ! null) || containsKey(key))? v: defaultValue;}作用&#xff1a;安全獲取值&#xff0c;若key不存在則返回默認值 示例&…

山東大學 2025 web數據管理期末復習總結

SDU-2025年-Web數據管理期末總結 考試題型 填空 &#xff1a;都來自于PPT中名詞解釋簡答題&#xff1a;需要背一些公式。 根據L老師上課提及的重點一共總結了87問題。 文章目錄 SDU-2025年-Web數據管理期末總結考試題型第1講 緒論此章不考 第2講 網絡爬蟲技術2.1 爬蟲是什么…

Spring框架的設計模式

Spring 框架深度集成了多種經典設計模式&#xff0c;這些模式支撐了其核心功能&#xff08;如IoC、AOP&#xff09;的實現&#xff0c;以下是關鍵模式及其應用場景的梳理&#xff1a; 1、工廠模式 工廠模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的設計模式…