2014-08-29 61 views
4

我正在学习如何重载“ - >”和文档说: “operator->再次调用它递归的值,直到操作符 - >到达,返回一个普通指针,然后,内建语义应用于该指针。“重载“ - >”(成员访问)递归

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

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

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

在另一方面可能需要避免这种行为,它怎么能做到?

+0

可否请你定义“普通指针”,我抬头一看什么shared_ptr的“特殊指针” – CoffeeandCode 2014-08-29 16:49:43

+0

,但如果是递归? – 2014-08-29 16:50:10

+1

“普通指针”是C++的“普通指针”。 – 2014-08-29 16:50:54

回答

2

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

我认为你误解了它的功能。它不用于取消引用列表元素并保持取消引用下一个元素。每次打电话给operator->时,你会得到一个不同的类型,问题是如果第二种类型也有operator->它会被调用,这可能会再次返回一个不同的类型。想象一下,它是像x->->->ix->next->next->next是否有帮助

的现实世界中使用的例子可以帮助也一样,也许我缺少一个模型,其中应用的行为。

它可以用于Execute Around Pointer模式。

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

电话运营商明确:

auto x = p.operator->(); 
7

那么,->运营商在评价者的特殊情况下工作。

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

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

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

非正式地说,每当你使用智能指针时,你都会真实地使用这些超载运算符的“递归”属性。如果你有一个智能指针sptr指向一个带有成员member的类对象,那么成员访问语法保持完全自然,例如, sptr->member。您不必将其作为sptr->->membersptr->.member来执行,具体原因是超载->的隐式“递归”属性。

注意,当您使用操作语法调用重载->操作,即object->member语法这个递归行为仅适用。但是,您也可以使用常规成员函数调用语法来调用您的超载->,例如object.operator ->()。在这种情况下,该调用是作为普通函数调用进行的,并且不会发生->的递归应用。这是避免递归行为的唯一方法。如果要实现重载->操作返回类型不支持->运营商的进一步应用程序(例如,你可以定义一个重载->返回int),那么object.operator ->()将调用您的重载实现的唯一途径。任何使用object->member语法的尝试都是不合格的。

+0

有指向成员的指针,所以不知何故程序员也可以访问“成员”概念。 – 2014-08-29 16:53:54

+0

但问题是关于递归! – 2014-08-29 16:54:24

+2

@GeorgeKourtis,但是当右操作数是一个指向成员的指针时,你必须声明'x - > * pmf'不是'x-> name',所以它不能通过'operator->'来访问 – 2014-08-29 16:54:53