过载" - >" (成员访问)递归

时间:2014-08-29 16:42:02

标签: c++

我正在学习如何超载“ - >”并且文件说: “operator->在它返回的值上再次被调用,直到达到operator->返回一个普通指针。之后,内置语义应用于该指针。”

虽然很清楚文档说的是什么,但基本上是超载的“ - >”一个类可以使用自己的“特殊指针”本身就是一个重载的“ - >”可以给出一个“特殊指针”等,直到找到“普通指针”,我找不到它的实际使用示例(除非它用于查找链接列表的最后一个元素)。

有人可以解释幕后的内容是什么(因为这种可能性没有提供“普通指针” - 所以我没有看到任何理由为它提供“特殊指针”)。

真实世界使用的一个例子也可能有所帮助,因为我可能错过了应用该行为的模型。

另一方面可能需要避免这种行为,怎么可能呢?

2 个答案:

答案 0 :(得分:7)

嗯,->运算符在特殊情况下工作。

可以称之为伪二元运算符。根据它的自然语法pointer->member,它需要两个操作数:左侧的正常运行时操作数和右侧的相当“奇怪的”成员名称操作数。第二个操作数的“奇怪性”源于C ++语言没有用户可访问的概念来表示这些操作数。语言中没有任何内容可以将成员名称表示为操作数。没有办法通过代码将成员名称“传递”给用户定义的实现。成员名称是一个编译时实体,在这方面远程类似于常量表达式,但C ++中没有常量表达式可以指定成员。 (有成员指针的表达式,但成员本身没有)。

这在指定重载->运算符的行为时会产生相当明显的困难:我们如何将->右侧指定的内容(即成员名称)与写入的代码连接起来用户?不可能直接这样做。摆脱这种情况的唯一方法是间接地执行此操作:强制用户将重载的->运算符的用户定义功能引导到某些现有内置运算符的功能中。内置运算符可以通过其核心语言功能自然地处理成员名称。

在这种特殊情况下,我们只有两个候选人可以将重载->的功能引导至:内置->和内置.。为该角色选择内置->是合乎逻辑的。这产生了一个有趣的副作用:编写重载->运算符(由编译器隐式解包)的“链式”(递归)序列甚至无限递归序列(形成不良)的可能性。

非正式地说,每次使用智能指针时,都可以实际使用重载->运算符的这些“递归”属性。如果您有一个智能指针sptr指向具有成员member的类对象,则成员访问语法保持完全自然,例如sptr->member。您不必专门为sptr->->membersptr->.member执行此操作,因为重载->的隐式“递归”属性。

请注意,仅当您使用 operator 语法调用重载的->运算符(即object->member语法)时,才会应用此递归行为。但是,您也可以使用常规成员函数调用语法来调用重载的->,例如object.operator ->()。在这种情况下,调用作为普通函数调用执行,并且不发生->的递归应用。这是避免递归行为的唯一方法。如果您实现了重载的->运算符,其返回类型不支持->运算符的其他应用程序(例如,您可以定义一个返回->的重载int,那么object.operator ->()将是调用重载实现的唯一方法。任何使用object->member语法的尝试都将是不正确的。

答案 1 :(得分:2)

  

我找不到真实使用它的例子(除非它用于查找链接列表的最后一个元素)。

我认为你误解了它的作用。它不用于取消引用列表元素并继续解除引用下一个元素。每次你打电话给operator->你会得到一个不同的类型,关键是如果第二种类型也有一个operator->它会被调用,这可能会返回一个不同的再次输入。想象一下,如果有帮助,x->->->i而不是x->next->next->next

  

真实世界使用的一个例子也可能有所帮助,因为我可能错过了应用该行为的模型。

它对Execute Around Pointer模式很有用。

  

另一方面可能需要避免这种行为,怎么可能呢?

明确地呼叫运营商:

auto x = p.operator->();