为何B转A的类转换运算符无法隐式调用?代码示例解析
问题原因分析
1. 2 - a 编译通过的原因
2 是 int 类型,a 是 A 类型,编译器在重载决议时会找到两个合法的候选路径:
- 路径一:利用
A的operator int()把a隐式转换为int,然后调用内置的int减法运算符(仅一次用户定义转换,符合规则)。 - 路径二:利用
A的int构造函数把2隐式转换为A对象,然后调用A的成员operator-(同样是一次用户定义转换,符合规则)。
两种路径都合法,因此编译通过。
2. b - a 编译失败的原因
b 是 B 类型,a 是 A 类型,问题核心在于成员运算符的匹配规则和用户定义转换的限制:
- 首先,
B类没有定义接受A作为参数的成员operator-,全局也没有对应的非成员operator-(B, A)。 - 其次,虽然
B可以通过operator A()隐式转换为A,但A的成员operator-要求左操作数必须是A类型(或其派生类)—— 成员运算符的调用是基于左操作数的原始类型的,编译器不会自动将左操作数B转换为A来调用A的成员运算符。 - 另一种可能的路径:把
a转换为int,同时把b转换为int,但这需要两次用户定义转换(B→A→int),违反了「每个参数最多允许一次用户定义隐式转换」的规则,因此也不可行。
如果把 A 的成员 operator- 改为非成员函数:
A operator-(const A& lhs, const A& rhs) { return lhs._a - rhs._a; }
此时编译器就能将 B 隐式转换为 A(一次转换),匹配这个非成员运算符,b - a 就能正常编译。
内容的提问来源于stack exchange,提问作者modjtabaf
相关产品推荐
相关产品推荐

