C++函數重載的一點問題
問題
#include <iostream>
#include <vector>
enum A { Value = 1 };
void a(std::vector<int>) {
std::cout << "a1" << std::endl;
}
void a(A e) {
std::cout << "a2:" << e << std::endl;
}
//void a(int t) {
// std::cout << "a3:" << t << std::endl;
//}
int main() {
a({});
// a({1});
// a({Value});
// a({1,2});
return 0;
}
這段代碼,想想會輸出哪個?
我會選擇輸出 a1,我想應該有很多人跟我的選擇是一致的。
因為按照C的習慣,enum A 實際上可能是一個整形,而{}最可能的是個數組,
最符合直覺的結果肯定是輸出a1
但實際上,無論用g++還是clang++,輸出的結果都是 a2:0
分析
接著上面的代碼,如果在main中寫下面的代碼:
A c = {};
std::cout << "A:" << c << std::endl;
它會編譯通過,并始終輸出A:0,這證明enum是可以用{}初始化的
那其他類型呢?
是的,幾乎所有的基礎類型都可以
顯然,編譯器認為,初始化一個enum A,比初始化一個std::vector<int>要簡單,
在函數重載中,void a(A e)是一個更直接的匹配
同樣如果注釋void a(A e)函數,將void a(int t)解注釋,應該知道會輸出什么結果了。
思考1
這讓我想起了int i(1);這種直接初始化方式。那這與上面的列表初始化有什么不同?
int i = 1.1; // 正確
int i = {1.1}; // 編譯錯誤
int i(1.1); // 正確
由此可見,列表初始化會顯得更安全,因為它禁止窄化轉換,推薦在需要嚴格類型檢查時使用。
但是在c中,有不同的情況
int i = 1.1; // 正確
int i = {1.1}; // 正確
int i(1.1); // 錯誤
顯然,c支持基礎類型的列表初始化,并且c也允許a((int){1.1});這種調用方式,這樣語言的語法才是自洽完整的。
所以,如果一開始的問題答錯了,其實跟c++關系不大,而是對c的認知還差點意思,咱還得學習。
所謂活到老,學到老
結論
在調用重載函數時,需要當心!!!不然很容易出一些難以查找的BUG

浙公網安備 33010602011771號