使用"operator T*()"而不是"T* operator->()"进行成员访问
Use "operator T*()" instead of "T* operator->()" for member access
表达式x->y
要求x
是完成类型的指针,或者当x
是类的实例时,需要为x
定义的operator->()
。但是,当后者是这种情况时,为什么不是我可以使用转换函数(即,将对象x
转换为指针)?例如:
struct A
{
int mi;
operator A*() { return this; }
};
int main()
{
A a;
a[1]; // ok: equivalent to *(a.operator A*() + 1);
a->mi; // ERROR
}
这给出了一个错误消息:
error: base operand of '->' has non-pointer type 'A'
但是问题是,为什么不使用a.operator A*()
,就像a[1]
一样?
这是由于表达式运营商的特殊超载分辨率规则所致。对于大多数运营商而言,如果操作数具有类型是类或枚举的类型,则操作员功能和内置运算符相互竞争,并且过载分辨率确定要使用哪种。这就是a[1]
发生的情况。但是,有一些例外,适用于您的案件的例外是标准中的[13.3.1.2p3.3](所有报价中的强调我的强调):
(3.3) - 对于操作员
,
,Unary操作员&
或操作员->
, 内置候选人集为空。对于所有其他运营商, 内置候选人包括所有候选运营商功能 与给定的操作员相比,在13.6中定义了,
- 具有相同的操作员名称,
- 接受相同数量的操作数,
- 接受可以根据13.3.3.1和
转换给定的操作数或操作数的操作数类型- 没有任何不是函数模板专业化的非成员候选人的参数类型列表。
因此,对于a[1]
,用户定义的转换用于获取一个可以应用内置[]
运算符的指针,但是对于那里的三个例外,只有运算符函数首先考虑到(并且那里'在这种情况下)。后来,[13.3.1.2p9]:
如果操作员是操作员
,
,则单位操作员&
或 操作员->
,,并且没有可行的功能,那么操作员是 假定是内置的操作员,并根据 第5条。
简而言之,对于这三个操作员,只有在其他所有操作失败时才考虑内置版本,然后他们必须在操作数上工作,而无需任何用户定义的转换。
据我所知,这样做是为了避免混淆或模棱两可的行为。例如,内置运算符,
和&
对于(几乎)所有操作数都是可行的,因此,如果在过载的正常步骤中,将它们过载它们将无效,则将它们无法正常工作。
运算符->
在超载时具有异常行为,因为它可能导致一系列过载的->
的调用链,如[Note 129]中所述:
如果
operator->
函数返回的值具有类类型,则 可能会导致选择并调用另一个operator->
功能。这 进程重复直到operator->
函数返回值 非班级类型。
我想您会从超载->
的类开始,该类返回其他类型的对象,该类型不会超载->
,但具有用户定义的转换为指针类型,从而导致最终内置->
的调用被认为有些混乱。将其限制为明确的->
超载看起来更安全。
所有报价均来自N4431,即当前的工作草案,但是相关部分自C 11。
我没有交手的标准,也许有人可以进来并在我之后提供更好的答案。但是,从cppreference.com上的叙述中:
内置操作员的左操作数。操作员 ->是完整标量T型(用于操作员)的表达式。正确的操作数是T或T的基本类之一的成员对象或成员函数的名称,例如Expr.Member,可选的合格,例如expr.name :: member,可选地使用模板disambiguator,例如expr.template成员。 表达式A-> b完全等于(*a).b对于内置类型。如果提供了用户定义的操作员 ->,则在其递归返回的值上再次调用操作员 ->,直到达到运算符 ->到达返回普通指针的操作员。之后,将内置语义应用于该指针。
强调是我的。
如果操作员 ->要在另一个操作员的结果上递归调用 ->(将具有指针返回类型),这强烈暗示操作员 ->必须在指针类型上调用。
<</p>- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 助记符和指向成员语法的指针
- 用于访问容器<T>数据成员的正确 API
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 嵌套在类中时无法设置成员数据
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 将函数类成员映射到类本身内部
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 将公共但非静态的成员函数与ALGLIB集成
- 多成员Constexpr结构初始化
- 是否需要使用 - &gt;运算符在C 中调用成员函数时