|
|
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。出於同樣的原因,第二個模板實參必須是常量表達式(不能傳遞變數)。![]() 函式 | ![]() 目錄 | ![]() 名稱可見性 |