为什么这个 class 不隐式转换为指针?

Why doesn't this class implicitly convert to a pointer?

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->),但我不明白为什么不进行隐式转换。

因为 C++ 只有在知道应该转换成什么时才会隐式转换 class 实例。如果你使用像 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; }
}

这是为 -> 运算符定义重载解析的结果。引用自 C++14 [over.match.oper]/3:

For the operator ,, the unary operator &, or the operator ->, the built-in candidates set is empty.

也就是说,如果->的左边操作数是class或者枚举类型,那么->就永远不会有它的内置意义;相反,operator-> 作为左侧操作数 class 的成员的名称查找必须 成功。

如果内置 -> 运算符是候选者,则编译器可以考虑隐式转换,允许 B 转换为内置 -> 可以接受,但它不是候选人,所以不会发生这种情况。

but I don't understand why implicit conversion doesn't take place.

它没有发生的上下文。operator-> 隐式应用于指针,或应用于定义了该运算符的 class 类型。但仅此而已。编译器不会通过其他序列来寻找它。在这种情况下,b-> 的内置候选集为空,没有 operator->,因此编译错误。

您只想添加:

A* operator->() { return &a; }