struct A {
int i;
};
struct B {
A a;
operator A*() { return &a; }
};
int main(int argc, char *argv[])
{
B b;
return b->i;
}
g++
举报error: base operand of ‘->’ has non-pointer type ‘B’
为什么呢?我已经想出如何绕过这个问题(使用operator->
),但我不明白为什么不进行隐式转换。
答案 0 :(得分:5)
这是为->
运算符定义重载决策的结果。引自C ++ 14 [over.match.oper] / 3:
对于运算符
,
,一元运算符&
或运算符->
,内置候选集为空。
也就是说,如果->
的左侧操作数是类或枚举类型,那么->
将永远不会有其内置含义;相反,作为左侧操作数的成员的operator->
的名称查找必须成功。
如果内置->
运算符是候选者,那么编译器可以考虑允许B
转换为内置->
可以的类型的隐式转换采取,但它不是候选人,所以这不会发生。
答案 1 :(得分:3)
因为C ++只知道它应该转换为什么时才会隐式转换它。如果你使用像b->
这样的表达式,它就不能知道你希望将它转换为什么指针类型(如果有的话),并且只使用普通运算符(未定义)除非超载):
B b;
// calls B::operator-> since that's what you tell it to do
b->i;
// calls B::operator A* since it knows it's implicitly converting to A*
A *a = b;
如果你想在这里使用第一个表达式,正确的方式是重载operator->
:
class B {
/* ... */
A* operator ->() { return &a; }
}
答案 2 :(得分:3)
但我不明白为什么不进行隐式转换。
没有任何上下文可以发生。operator->
隐式应用于指针,或者适用于定义了该运算符的类类型。但就是这样。编译器没有其他序列可以找到它。在这种情况下,b->
的内置候选集是空的,没有operator->
,因此编译错误。
您只想添加:
A* operator->() { return &a; }