C++ operator*声明为成员与全局函数的重载歧义差异问题
两种写法的差异本质
差异来自C++重载决议的匹配规则,以及成员函数隐含this参数的特殊属性:
重载决议会逐参数对比两个候选函数的转换等级,只有当一个候选的所有参数转换等级都不低于另一个,且至少有一个参数的转换等级更高时,才会被选中,否则就判定为歧义。
场景1:点乘声明为全局函数(无歧义)
此时参与重载的两个候选为:
- 标量乘:
Vector operator*(const Vector& v, float k) - 全局点乘:
float operator*(const Vector& v1, const Vector& v2)
调用v * 3时的参数匹配情况:
- 第一个参数是non-const的Vector对象
v:两个重载都要求const Vector&类型,non-const对象绑定const引用的限定转换等级完全一致,没有优劣之分。 - 第二个参数是int类型的
3:标量乘只需要做int转float的标准转换,点乘需要调用单参数构造函数做int转Vector的用户定义转换,标量乘的转换等级明显更高。
因此重载决议会直接选择标量乘,不存在歧义。
场景2:点乘声明为成员函数(出现歧义)
此时参与重载的两个候选为:
- 标量乘:
Vector operator*(const Vector& v, float k) - 成员点乘:
float Vector::operator*(const Vector& v)(注意该成员函数没有加const修饰)
调用v * 3时的参数匹配情况:
- 第一个参数对应成员函数的隐含
this指针:成员点乘的this是non-const的Vector*,直接绑定non-const的v属于完美匹配,比标量乘需要的const限定转换等级更高。 - 第二个参数是int类型的
3:标量乘的int转float标准转换,比成员点乘需要的用户定义转换等级更高。
此时两个候选各有一个参数的转换等级优于对方,没有任何一个候选整体更优,编译器就会报歧义错误。
内容的提问来源于stack exchange,提问作者vanger
相关产品推荐
相关产品推荐

