如題,今天遇到一個很奇怪的問題,簡化示例代碼如下:
#include <iostream>
#include <string>
class TestClass{
public:
void TestFunction(const std::string& test_string)
{
std::cout << "string function!" << std::endl;
}
void TestFunction(bool test_bool)
{
std::cout << "bool function!" << std::endl;
}
};
int main()
{
TestClass tmp;
tmp.TestFunction("123456");
return 0;
}
可以看到TestClass類中TestFunction進行了重載,參數分別爲string和bool,此時如果如示例中傳入了"123456"這一字面常量時,實際上傳入的是const char指針類型。類似於如下
const char* tmp_string = "123456";
tmp.TestFunction(tmp_string );
期望的匹配是該類型觸發隱式轉換構造爲string,從而匹配string參數的重載函數。但是實際上匹配到的是bool參數的函數。除非顯式強轉如:
tmp.TestFunction(std::string("123456"));
查了下《C++ primer》才知道,基礎知識有缺漏。
C++編譯時,編譯器會根據傳入實參進行重載函數匹配,此時可能發生實參類型到形參類型的轉換,這裏編譯器將實參類型到形參類型的轉換分成幾個等級,排序如下:
1.精確匹配:
-
實參類型和形參類型相同
-
實參從數組類型或函數類型轉換成對應的指針類型
-
向實參添加頂層const或者從實參中刪除頂層const
2.通過const轉換實現的匹配
底層const的添加,如:
int i;
void testFunction(cosnt int* test_int);
int main()
{
testFunction(&i);
}
3.通過類型提升實現的匹配
類型提升爲類型長度寬度的提升,如short->int,float->double。
4.通過算數類型轉換或指針轉換實現的匹配
算數類型轉換如int->double,需要與類型提升區分開。
指針轉換除了各種指針類型之間的轉換,還存在一種指針類型向bool類型自動轉換的機制,如果指針的值爲0,轉換結果爲false,否則轉換結果是True,指針不存在轉爲bool外其他非指針類型的隱式轉換。
5.通過類類型轉換實現的匹配
類類型轉換一般爲子類向父類轉換,或者形參類構造函數支持傳入形參類型,例如開頭處提到的"1234"->std::string。
上述優先級從1到5依次降低,1-4可以認爲是C++內置轉換,5爲自定義轉換,則本次遇到的坑"123456"->bool屬於優先級4,而“123456”->std::string 屬於自定義的優先級5,自然匹配到bool類型的重載函數了。
基礎還是要打紮實,書還是要多看幾遍啊。