[英]Behavior of function overloading with const
我正在研究g ++,在這里我試圖通過向參數添加const
來重載函數。 它工作正常,當它運行時,它調用沒有const
是什么原因它調用沒有const
void print(const std::string& str){std::cout << "const" << str << std::endl;} void print(std::string& str){std::cout << str << std::endl;} int main() { std::string temp = "hello"; print(temp); return 0; }
引用綁定是一個標識類別§13.3.3.1.4 )但由於后者更符合cv,對於§13.3.3.2,非const是首選(來自標准的示例代碼):
int f(const int &);
int f(int &);
int i;
int j = f(i); // calls f(int &)
這是標准行為。 任何其他行為都會導致瘋狂行為。 特別是,非const函數根本不可調用。
const是方法簽名的一部分。 覆蓋僅適用於具有相同簽名的方法。 當您使用基類的const方法調用子類的const方法時,這種行為是為了避免相反的情況。
原因是[over.ics.rank] / 3中的這一部分明確涵蓋了這個案例:
標准轉換序列
S1
是比標准轉換序列S2
更好的轉換序列
[...]
-S1
和S2
是引用綁定(8.5.3),引用引用的類型除了頂級cv限定符之外是相同的類型,S2
引用的引用引用的類型更符合cv比S1
引用的引用所引用的類型。
S1
對應於第二次過載而S2
對應於第一次過載。
是什么原因它調用沒有
const
你總是試圖選擇最專業的東西。 就像在函數模板的部分排序中那樣,在重載解析中就是這種情況。 第二個重載比第一個重載更專業,因為第一個可以使用參數調用,第二個不能被調用 - 這是此規則背后的基本推理。
重載通過匹配參數的類型(包括限定符)來工作。 在你的情況下, temp
類型是std::string
而不是const std::string
。 你只用一個文字常量初始化它,它本身不是常數。
考慮以下:
std::string temp( "hello" ) ;
print(temp); // hello
print( std::string("hello") ) ; // consthello
print( "hello" ) ; // consthello
print( static_cast<const std::string>(temp) ) ; // consthello
const std::string temp2( "hello" ) ;
print(temp2); // consthello
如果要刪除非const版本,則所有三個都將調用剩余的const重載。 在此示例中,實際上只有const版本是必需的(並且是首選的),因為兩個版本都不修改字符串對象。
另一方面,如果你刪除了非const版本,除了上面的第一個例子之外,沒有任何函數匹配,並且構建將失敗。 也就是說非const對象可以安全地作為const參數傳遞,但是const對象不能作為非const參數傳遞,因為該函數不“承諾”不修改對象。 您可以通過const_cast
將const強制轉換為非const參數,如下所示:
const std::string temp2("hello") ;
print( const_cast<std::string&>(temp2) ) ; // hello
但是如果print()
在這種情況下試圖修改對象,結果是不確定的 ,那么請考慮這種做法不安全。
使參數const表示意圖,允許編譯器在代碼嘗試修改對象或通過非const參數將其傳遞給其他函數時發出診斷。 它還可能為編譯器提供優化可能性。
因為調用函數采用std::string const&
需要兩個隱式轉換:一個到std::string const
,一個到std::string const&
; 而調用函數采用std::string&
只需要一次隱式轉換(到std::string&
),因此首選。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.