为什么这个 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; }
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; }