为什么这个类没有隐式转换为指针?

时间:2016-09-27 20:32:34

标签: c++ conversion-operator

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

3 个答案:

答案 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; }