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

posted @ 2025-02-19 15:58  yxfangcs  阅读(5)  评论(0)    收藏  举报