日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

C++函數(shù)模板詳解,輕松實現(xiàn)通用函數(shù)

來源: 責(zé)編: 時間:2023-12-25 09:35:45 255觀看
導(dǎo)讀一、函數(shù)模板1.編寫通用函數(shù)您也可以為獨(dú)立的函數(shù)編寫模板。其語法與類模板類似。例如,您可以編寫以下通用函數(shù)來在數(shù)組中查找一個值并返回其索引:static const size_t NOT_FOUND { static_cast<size_t>(-1) };template

一、函數(shù)模板

1.編寫通用函數(shù)

您也可以為獨(dú)立的函數(shù)編寫模板。其語法與類模板類似。例如,您可以編寫以下通用函數(shù)來在數(shù)組中查找一個值并返回其索引:Wr628資訊網(wǎng)——每日最新資訊28at.com

static const size_t NOT_FOUND { static_cast<size_t>(-1) };template <typename T>size_t Find(const T& value, const T* arr, size_t size) {    for (size_t i { 0 }; i < size; i++) {        if (arr[i] == value) {            return i; // 找到了; 返回索引。        }    }    return NOT_FOUND; // 沒找到; 返回 NOT_FOUND。}

注意:當(dāng)然,當(dāng)元素未找到時,您可以不返回某種哨兵值(如 NOT_FOUND),而是改寫此代碼以返回 std::optional<size_t> 而不是 size_t。這將是使用 optional 的有趣練習(xí)。Wr628資訊網(wǎng)——每日最新資訊28at.com


Wr628資訊網(wǎng)——每日最新資訊28at.com

Wr628資訊網(wǎng)——每日最新資訊28at.com

Wr628資訊網(wǎng)——每日最新資訊28at.com

2.Find() 函數(shù)模板的應(yīng)用

Find() 函數(shù)模板可以在任何類型的數(shù)組上工作。例如,您可以用它來在 int 數(shù)組中查找 int 的索引,或者在 SpreadsheetCell 數(shù)組中查找 SpreadsheetCell。您可以通過兩種方式調(diào)用該函數(shù):顯式地用尖括號指定類型參數(shù),或者省略類型并讓編譯器從參數(shù)中推斷出類型參數(shù)。以下是一些示例:Wr628資訊網(wǎng)——每日最新資訊28at.com

int myInt { 3 }, intArray[] {1, 2, 3, 4};const size_t sizeIntArray { size(intArray) };size_t res;// 通過推斷調(diào)用 Find<int>。res = Find(myInt, intArray, sizeIntArray);// 顯式地調(diào)用 Find<int>。res = Find<int>(myInt, intArray, sizeIntArray);// 其他示例double myDouble { 5.6 }, doubleArray[] {1.2, 3.4, 5.7, 7.5};const size_t sizeDoubleArray { size(doubleArray) };// 通過推斷調(diào)用 Find<double>。res = Find(myDouble, doubleArray, sizeDoubleArray);// 顯式地調(diào)用 Find<double>。res = Find<double>(myDouble, doubleArray, sizeDoubleArray);SpreadsheetCell cell1 { 10 }SpreadsheetCell cellArray[] { SpreadsheetCell { 4 }, SpreadsheetCell { 10 } };const size_t sizeCellArray { size(cellArray) };res = Find(cell1, cellArray, sizeCellArray);res = Find<SpreadsheetCell>(cell1, cellArray, sizeCellArray);

3.數(shù)組大小的自動推斷

之前的 Find() 函數(shù)實現(xiàn)需要作為參數(shù)之一的數(shù)組大小。有時編譯器知道數(shù)組的確切大小,例如,對于基于堆棧的數(shù)組。能夠在不需要傳遞數(shù)組大小的情況下調(diào)用 Find() 會很方便。這可以通過添加以下函數(shù)模板來實現(xiàn)。實現(xiàn)只是將調(diào)用轉(zhuǎn)發(fā)到之前的 Find() 函數(shù)模板。這也表明,函數(shù)模板可以像類模板一樣接受非類型參數(shù)。Wr628資訊網(wǎng)——每日最新資訊28at.com

template <typename T, size_t N>size_t Find(const T& value, const T(&arr)[N]) {    return Find(value, arr, N);}

這個版本的 Find() 語法看起來有點(diǎn)奇怪,但其使用非常直接,如下例所示:Wr628資訊網(wǎng)——每日最新資訊28at.com

int myInt { 3 }, intArray[] {1, 2, 3, 4};size_t res { Find(myInt, intArray) };

4.函數(shù)模板的定義和導(dǎo)出

與類模板方法定義一樣,函數(shù)模板的定義(不僅僅是原型)必須對使用它們的所有源文件可用。因此,如果多個源文件使用它們,您應(yīng)該將定義放在模Wr628資訊網(wǎng)——每日最新資訊28at.com

塊接口文件中并導(dǎo)出它們。Wr628資訊網(wǎng)——每日最新資訊28at.com

最后,函數(shù)模板的模板參數(shù)可以像類模板一樣有默認(rèn)值。Wr628資訊網(wǎng)——每日最新資訊28at.com

注意:C++ 標(biāo)準(zhǔn)庫提供了一個比這里展示的 Find() 函數(shù)模板更強(qiáng)大的 std::find() 函數(shù)模板。Wr628資訊網(wǎng)——每日最新資訊28at.com

Wr628資訊網(wǎng)——每日最新資訊28at.com

二、函數(shù)模板重載

1.函數(shù)模板與特化

理論上,C++ 語言允許您編寫函數(shù)模板特化,就像您可以編寫類模板特化一樣。然而,您很少需要這樣做,因為這樣的函數(shù)模板特化不參與重載解析,因此可能表現(xiàn)出意外的行為。相反,您可以用非模板函數(shù)重載函數(shù)模板。例如,您可能想為 const char* 類型的 C 風(fēng)格字符串編寫一個 Find() 重載,這個重載使用 strcmp()來比較,而不是用 operator==,因為 == 只會比較指針,而不是實際的字符串。以下是這樣的重載:Wr628資訊網(wǎng)——每日最新資訊28at.com

size_t Find(const char* value, const char** arr, size_t size) {    for (size_t i { 0 }; i < size; i++) {        if (strcmp(arr[i], value) == 0) {            return i; // 找到了; 返回索引。        }    }    return NOT_FOUND; // 沒找到; 返回 NOT_FOUND。}

這個函數(shù)重載的使用方式如下:Wr628資訊網(wǎng)——每日最新資訊28at.com

const char* word { "two" };const char* words[] { "one", "two", "three", "four" };const size_t sizeWords { size(words) };size_t res { Find(word, words, sizeWords) }; // 調(diào)用非模板函數(shù)。

如果您顯式指定模板類型參數(shù),如下所示,那么將調(diào)用函數(shù)模板,其中 T=const char,而不是 const charWr628資訊網(wǎng)——每日最新資訊28at.com

res = Find<const char*>(word, words, sizeWords);

2.重載與特化的選擇

在選擇重載函數(shù)模板時,應(yīng)該考慮到函數(shù)模板特化可能不參與重載解析的規(guī)則。通常,重載函數(shù)模板與非模板函數(shù)是一種更安全且可預(yù)測的方法,特別是當(dāng)涉及到特定類型的特定處理,如在處理 C 風(fēng)格字符串時使用 strcmp() 而不是默認(rèn)的等號運(yùn)算符。Wr628資訊網(wǎng)——每日最新資訊28at.com

三、類模板的友元函數(shù)模板

1.重載運(yùn)算符的函數(shù)模板

當(dāng)您想在類模板中重載運(yùn)算符時,函數(shù)模板非常有用。例如,您可能想為 Grid 類模板重載加法運(yùn)算符(operator+),以便將兩個網(wǎng)格相加。結(jié)果將是一個與兩個操作數(shù)中較小的 Grid 同等大小的 Grid。僅當(dāng)兩個單元格都包含實際值時,才會相加對應(yīng)的單元格。假設(shè)您想讓您的 operator+ 成為一個獨(dú)立的函數(shù)模板。定義應(yīng)該放在 Grid.cppm 模塊接口文件中,如下所示。該實現(xiàn)使用 <algorithm> 中定義的 std::min() 來返回兩個給定參數(shù)的最小值:Wr628資訊網(wǎng)——每日最新資訊28at.com

export template <typename T>Grid<T> operator+(const Grid<T>& lhs, const Grid<T>& rhs) {    size_t minWidth { std::min(lhs.getWidth(), rhs.getWidth()) };    size_t minHeight { std::min(lhs.getHeight(), rhs.getHeight()) };    Grid<T> result { minWidth, minHeight };        for (size_t y { 0 }; y < minHeight; ++y) {        for (size_t x { 0 }; x < minWidth; ++x) {            const auto& leftElement { lhs.m_cells[x][y] };            const auto& rightElement { rhs.m_cells[x][y] };            if (leftElement.has_value() && rightElement.has_value()) {                result.at(x, y) = leftElement.value() + rightElement.value();            }        }    }    return result;}

要查詢一個 optional 是否包含實際值,您使用 has_value() 方法,而 value() 用于檢索這個值。這個函數(shù)模板適用于任何 Grid,只要網(wǎng)格中存儲的元素類型有加法運(yùn)算符。這個實現(xiàn)的唯一問題是它訪問了 Grid 類的私有成員 m_cells。一個顯而易見的解決方案是使用公共 at() 方法,但讓我們看看如何讓函數(shù)模板成為類模板的友元。Wr628資訊網(wǎng)——每日最新資訊28at.com

3.使函數(shù)模板成為類模板的友元

在此示例中,您可以使運(yùn)算符成為 Grid 類的友元。然而,Grid 類和 operator+ 都是模板。您真正想要的是,對于特定類型 T 的每個 operator+ 實例化,都是同一類型的 Grid 模板實例化的友元。語法如下:Wr628資訊網(wǎng)——每日最新資訊28at.com

// 前向聲明 Grid 模板。export template <typename T>class Grid;// templatized operator+ 的原型。export template <typename T>Grid<T> operator+(const Grid<T>& lhs, const Grid<T>& rhs);export template <typename T>class Grid {public:    friend Grid operator+<T>(const Grid& lhs, const Grid& rhs);    // 省略其他內(nèi)容};

這種友元聲明很微妙:您在說,對于類型 T 的模板實例,operator+ 的 T 實例化是一個友元。換句話說,類實例化和函數(shù)實例化之間存在一對一的友元映射。特別注意 operator+ 上的顯式模板規(guī)范 <T>。這個語法告訴編譯器 operator+ 本身是一個模板。Wr628資訊網(wǎng)——每日最新資訊28at.com

3.模板參數(shù)推斷

編譯器根據(jù)傳遞給函數(shù)模板的參數(shù)推斷函數(shù)模板參數(shù)的類型。無法推斷的模板參數(shù)必須明確指定。例如,以下 add() 函數(shù)模板需要三個模板參數(shù):返回值的類型和兩個操作數(shù)的類型:Wr628資訊網(wǎng)——每日最新資訊28at.com

template <typename RetType, typename T1, typename T2>RetType add(const T1& t1, const T2& t2) {    return t1 + t2;}

您可以通過以下方式調(diào)用此函數(shù)模板,明確指定所有三個參數(shù):Wr628資訊網(wǎng)——每日最新資訊28at.com

auto result { add<long long, int, int>(1, 2) };

然而,因為模板參數(shù) T1 和 T2 是函數(shù)的參數(shù),編譯器可以推斷這兩個參數(shù),所以您可以只指定返回值類型來調(diào)用 add():Wr628資訊網(wǎng)——每日最新資訊28at.com

auto result { add<long long>(1, 2) };

這只有在要推斷的參數(shù)位于參數(shù)列表的最后時才有效。假設(shè)函數(shù)模板如下定義:Wr628資訊網(wǎng)——每日最新資訊28at.com

template <typename T1, typename RetType, typename T2>RetType add(const T1& t1, const T2& t2) {    return t1 + t2;}

您必須指定 RetType,因為編譯器無法推斷該類型。然而,由于 RetType 是第二個參數(shù),您也必須顯式指定 T1:Wr628資訊網(wǎng)——每日最新資訊28at.com

auto result { add<int, long long>(1, 2) };

您還可以為返回類型模板參數(shù)提供默認(rèn)值,以便在不指定任何類型的情況下調(diào)用 add():Wr628資訊網(wǎng)——每日最新資訊28at.com

template <typename RetType = long long, typename T1, typename T2>RetType add(const T1& t1, const T2& t2) {    return t1 + t2;}...auto result { add(1, 2) };

本文鏈接:http://www.www897cc.com/showinfo-26-53349-0.htmlC++函數(shù)模板詳解,輕松實現(xiàn)通用函數(shù)

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Java Lambda 表達(dá)式各種用法,你都會了嗎

下一篇: 拒絕寫重復(fù)代碼,試試這套開源的 SpringBoot 組件,效率翻倍

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 云林县| 玉树县| 龙岩市| 仲巴县| 汝阳县| 聂拉木县| 游戏| 勐海县| 义乌市| 台南县| 南城县| 保定市| 宝坻区| 万载县| 呈贡县| 平定县| 饶河县| 上虞市| 旌德县| 宁波市| 商丘市| 广宁县| 廉江市| 凌云县| 濮阳市| 合江县| 嘉峪关市| 抚顺市| 赞皇县| 称多县| 夏津县| 黄浦区| 房山区| 育儿| 鹰潭市| 甘南县| 邵阳县| 上高县| 车致| 榆林市| 台中市|