|
|
10 2.5 |
operate 的函式,但其中一個函式有兩個 int 型別的引數,而另一個函式有兩個 double 型別的引數。編譯器透過檢查函式呼叫時傳遞的實參型別,來確定在每種情況下應呼叫哪個函式。如果使用兩個 int 實參呼叫,它會呼叫具有兩個 int 形參的函式;如果使用兩個 double 實參呼叫,它會呼叫具有兩個 double 形參的函式。int 版本將其引數相乘,而 double 版本則將它們相除。通常不建議這樣做。一般而言,同名函式應具有至少相似的行為,但此示例表明,它們完全有可能行為不同。兩個過載函式(即兩個同名函式)具有完全不同的定義;從任何角度來看,它們都是不同的函式,只是恰好同名而已。 |
|
30 2.5 |
sum 函式針對不同的引數型別進行了過載,但函式體完全相同。sum 函式可以為多種型別過載,並且它們都具有相同的函式體是有道理的。對於這類情況,C++ 提供了定義具有泛型型別的函式的能力,這被稱為函式模板。定義函式模板的語法與常規函式相同,只是在前面加上 template 關鍵字和一系列用尖括號 <> 括起來的模板引數:template <模板引數> 函式宣告
class 或 typename 關鍵字後跟一個識別符號來成為泛型模板型別。然後,該識別符號可以在函式宣告中像常規型別一樣使用。例如,一個泛型的 sum 函式可以定義為: |
|
class 還是 typename 來指定泛型型別沒有區別(它們在模板宣告中是 100% 的同義詞)。SomeType(一個在尖括號內的模板引數中的泛型型別)後,SomeType 就可以在函式定義的任何地方使用,就像其他任何型別一樣;它可以用作引數的型別、返回型別,或用來宣告該型別的新變數。在所有情況下,它都代表一個泛型型別,該型別將在模板被例項化時確定。名稱 <模板實參> (函式實參)
sum 函式模板可以這樣呼叫: |
|
sum<int> 只是函式模板 sum 可能的例項化之一。在這種情況下,透過在呼叫中使用 int 作為模板實參,編譯器會自動例項化一個 sum 的版本,其中每次出現的 SomeType 都被替換為 int,就好像它是這樣定義的: |
|
|
|
11 2.5 |
T 作為模板引數名,而不是 SomeType。這沒有區別,而且 T 實際上是泛型型別中一個非常常見的模板引數名。sum。第一次使用 int 型別的實參,第二次使用 double 型別的實參。編譯器每次都例項化並呼叫了相應版本的函式。T 在 sum 函式內部也被用來宣告該(泛型)型別的區域性變數: |
|
result 將是一個與引數 a 和 b 以及函式返回型別相同的變數。T 被用作 sum 引數的特定情況下,編譯器甚至能夠自動推匯出資料型別,而無需在尖括號內顯式指定。因此,不必像下面這樣顯式指定模板實參: |
|
|
|
sum 時使用了不同型別的實參,編譯器可能無法自動推匯出 T 的型別。 |
|
x and y are equal |
are_equal 時使用了自動模板引數推導: |
|
|
|
int 型別的值,而浮點字面量總是產生 double 型別的值。因此,10 的型別總是 int,而 10.0 的型別總是 double。class 或 typename 引入的型別,還可以包含特定型別的表示式: |
|
20 30 |
fixed_multiply 函式模板的第二個引數是 int 型別。它看起來就像一個常規的函式引數,並且實際上也可以像常規引數一樣使用。fixed_multiply 函式的不同例項化版本,因此該引數的值在執行時永遠不會被傳遞:在 main 函式中對 fixed_multiply 的兩次呼叫,實際上呼叫了函式的兩個不同版本:一個總是乘以 2,另一個總是乘以 3。出於同樣的原因,第二個模板實參必須是常量表達式(不能傳遞變數)。函式 | 目錄 | 名稱可見性 |