C++函数重载与转换构造函数优先级:display_widget调用问询
问题1
当存在同名重载函数与转换构造函数时,转换构造函数会被调用吗?
问题2
假设重载函数:void display_widget( float f ); void display_widget( Apple a ); 请问:从float构造Apple的转换构造函数,与参数为float的重载函数,哪个优先级更高?
附示例代码
#include <iostream> class Apple { public: Apple() : f{ 0.0 } {}; float get_f() { return f; } Apple(float _f) : f{ _f } {}; operator float() { return f; } private: float f; }; void display_widget( float f ) { std::cout << "The float is: " << f << std::endl; } void display_widget( Apple a ) { std::cout << "The Apple is: " << a.get_f() << std::endl; } int main(int argc, char* argv[]) { display_widget(49.95); return 0; }
场景说明
我们有两个display_widget函数,一个接受Apple类型参数,另一个接受float类型参数。观察main函数中的语句:display_widget(49.95);
以下哪个伪代码能正确描述执行过程:
| 选项1 | 选项2 |
|---|---|
display_widget( float f ); | a = Apple( float _f ); |
display_widget( Apple a ); |
解答
直接给结论:选项1的执行过程是正确的——编译器会优先调用参数为float的重载函数,不会触发从float到Apple的转换构造函数。
背后的逻辑是C++重载决议的核心规则:优先选择隐式转换步骤最少的函数调用。这里传入的49.95是double字面量,它只需要一次标准内置类型转换就能匹配float参数的重载;而如果要调用Apple参数的版本,需要先把double转成float,再通过转换构造函数生成Apple对象——这是两次转换(标准转换+用户自定义转换),优先级远低于前者。
回到问题1:当存在同名重载函数和转换构造函数时,转换构造函数不一定会被调用。只有当没有更匹配的重载函数(即不需要转换或转换步骤更少的函数)存在时,编译器才会考虑触发转换构造函数来匹配重载。比如如果把接受float的display_widget注释掉,编译器就会自动把49.95转成float,再通过转换构造函数生成Apple对象,调用对应的重载函数。
内容的提问来源于stack exchange,提问作者Toothpick Anemone

