[英]Function Overloading Based on Value vs. Const Reference
是否聲明如下內容
void foo(int x) { std::cout << "foo(int)" << std::endl; }
void foo(const int &x) { std::cout << "foo(const int &)" << std::endl; }
有道理嗎? 調用者如何區分它們? 我試過了
foo(9); // Compiler complains ambiguous call.
int x = 9;
foo(x); // Also ambiguous.
const int &y = x;
foo(y); // Also ambiguous.
目的似乎是區分具有臨時性(即9
)和“常規”參數傳遞的調用。 第一種情況可能允許函數實現采用優化,因為很明顯參數將在之后處理(這對於整數文字絕對沒有意義,但對於用戶定義的對象可能有意義)。
但是,當前的 C++ 語言標准沒有提供專門針對參數的“l/r 值”重載的方法 - 作為參數傳遞給函數的任何 l 值都可以隱式轉換為引用,因此歧義是不可避免。
C++11 引入了一個類似目的的新工具——使用r-value 引用,你可以重載如下
void foo(int x) { ... }
void foo(const int &&x) { ... }
...和foo(4)
(作為參數傳遞的臨時 r 值)將導致編譯器在int i = 2; foo(i)
時選擇第二個重載int i = 2; foo(i)
int i = 2; foo(i)
會選擇第一個。
(注意:即使使用新工具鏈,也無法區分示例中的案例 2 和案例 3!)
你可以用一個模板來做到這一點:
template<typename T> void foo(T x) { ... }
然后你可以通過值或引用調用這個模板:
int x = 123;
foo<int>(x); // by value
foo<int const&>(x); // by refernce
調用者如何區分它們?
在這種情況下無法區分。 無論是過載功能有相同的類型的基本數據類型作為參數。 並且通過引用並不計入不同的類型。
您可以使用static_cast
顯式選擇要調用的重載:
#include <iostream>
void foo(int x) { std::cout << "foo(int)" << std::endl; }
void foo(const int &x) { std::cout << "foo(const int &)" << std::endl; }
int main()
{
int x = 0;
auto f1 = static_cast< void(*)(int) >(foo);
f1(x);
auto f2 = static_cast< void(*)(const int&) >(foo);
f2(x);
}
但是,您應該先問問自己為什么要提供這兩個重載。 要么您可以復制,要么不能。 兩者同時? 為什么? 還使得調用者必須明確選擇重載,這違背了函數重載的目的。 如果你真的想要考慮提供兩個函數:
void foo_copying(int x) { std::cout << "foo(int)" << std::endl; }
void foo_non_copying(const int &x) { std::cout << "foo(const int &)" << std::endl; }
不是在 C++ 中。 Erlang 和 Haskell 等函數式語言通過允許您根據參數值指定函數重載而更加接近,但包括 C++ 在內的大多數命令式語言都需要基於方法簽名的重載; 即每個參數的數量和類型以及返回值的類型。
簽名中的const
關鍵字定義的不是參數的類型,而是它在函數內的可變性; 如果被函數修改或通過引用傳遞給任何不使用const
函數,“ const
”參數將產生編譯器錯誤。
編譯器不能。 foo 的兩個定義都可以用於 int 的所有“變體”。
在第一個 foo 中,制作了 int 的副本。 復制 int 總是可能的。
在第二個 foo 中,傳遞了對 const int 的引用。 由於任何 int 都可以轉換為 const int,因此也可以傳遞對它的引用。
由於這兩種變體在所有情況下都有效,因此編譯器無法選擇。
如果您使用以下定義,事情就會變得不同:
void foo (int &x);
現在用foo(9)
調用它將采用第一種選擇,因為您不能將 9 作為非常量 int 引用傳遞。
另一個例子,如果你用一個復制構造函數是私有的類來替換 int ,那么調用者就不能復制這個值,第一個 foo 變體將不會被使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.