函數重載與函數模板
函數重載
函數組成
返回類型 函數名稱(參數列表){函數體}
函數簽名:函數名稱(參數列表)
C++ 允許定義同名函數,前提是它們具有不同的簽名。這被稱為函數重載 。
C++ 編譯器通過檢查調用中參數的數量、類型和順序來選擇要調用的適當函數。
//重載函數
//函數名稱一致,但參數列表中參數類型、順序不同
int square(int x){return x*x;
}
double square(double y){return y*y;
}
函數重載的目的:函數重載用于創建多個同名函數,這些函數執行類似任務,但處理不同類型的數據。
編譯器如何區分重載函數
重載函數通過其簽名來區分。簽名是函數名稱及其參數類型(按順序排列 )的組合。類型安全鏈接可確保調用恰當的函數,且實參的類型與形參的類型相符。為實現類型安全鏈接,編譯器會在內部對每個函數標識符進行編碼,編碼時納入其參數的類型 —— 這一過程稱為名稱修飾(name mangling )。這些編碼因編譯器而異,因此,要為特定平臺創建可執行文件而進行鏈接的所有內容,都必須使用該平臺對應的同一編譯器進行編譯。
下圖為由 GNU C++ 在匯編語言中生成的經過修飾的函數名稱 。
如果函數簽名一致,但返回類型不同,會造成編譯錯誤
創建具有相同參數列表但不同返回類型的重載函數會導致編譯錯誤。編譯器僅通過參數列表來區分重載函數,這些函數的參數數量不必相同。
如果一個函數省略了默認參數,可能會與另一個重載函數的調用形式完全相同,這也會引發編譯錯誤。
例如,若存在一個顯式不接受任何參數的函數,以及另一個同名但包含所有默認參數的函數,那么當嘗試以不傳遞任何參數的方式調用該函數名時,就會導致編譯錯誤——編譯器無法明確確定應選擇哪個版本的函數。
函數模板
函數模板產生的背景
重載函數通常對不同數據類型執行類似的操作。如果對于每種數據類型,程序邏輯和操作都是相同的,那么使用函數模板可以更緊湊、便捷地實現重載。你只需編寫一個函數模板定義,C++ 會自動生成獨立的函數模板特化版本(也稱為模板實例化),以適配所提供參數類型的每種調用類型。因此,單個函數模板定義了一個重載函數家族。使用模板進行編程也稱為泛型編程。
定義了一個最大值函數模板,該模板返回三個值中的最大值
所有函數模板定義均以template關鍵字開頭,后跟包含在尖括號(<>)中的模板參數列表。
模板參數列表中的每個參數都以關鍵字typename或keyword class作為前綴。
類型參數是基本類型或用戶定義類型的占位符。這些占位符(在本例中為T)用于指定函數參數的類型、函數的返回類型,以及在函數定義體中聲明變量。函數模板的定義方式與其他函數類似,但使用類型參數作為實際數據類型的占位符。
頭文件maximum.h
// template <關鍵字 占位符>
template <typename T> // or template <class T>
T maximum(T value1, T value2, T value3) { T maximumValue{value1}; // assume value1 is maximum // determine whether value2 is greater than maximumValueif (value2 > maximumValue) { maximumValue = value2; } // determine whether value3 is greater than maximumValueif (value3 > maximumValue) { maximumValue = value3; } return maximumValue; }
main.cpp
// Function template maximum test program.
#include <iostream>
#include "maximum.h" // include definition of function template maximum
using namespace std;int main() {// demonstrate maximum with int valuescout << "Input three integer values: ";int int1, int2, int3;cin >> int1 >> int2 >> int3;// invoke int version of maximumcout << "The maximum integer value is: "<< maximum(int1, int2, int3); // demonstrate maximum with double valuescout << "\n\nInput three double values: ";double double1, double2, double3;cin >> double1 >> double2 >> double3;// invoke double version of maximumcout << "The maximum double value is: "<< maximum(double1, double2, double3);// demonstrate maximum with char valuescout << "\n\nInput three characters: ";char char1, char2, char3;cin >> char1 >> char2 >> char3;// invoke char version of maximumcout << "The maximum character value is: "<< maximum(char1, char2, char3) << '\n';}