运算符>的递归应用

recursive application of operator->

本文关键字:递归 应用 运算符      更新时间:2023-10-16

据说箭头运算符是递归应用的。但是当我尝试执行以下代码时,它打印乱码时应该打印 4。

class dummy
{
public:
    int *p;
    int operator->()
    {
        return 4;
    }
};
class screen 
{
public:
    dummy *p;
    screen(dummy *pp): p(pp){}
    dummy* operator->()
    {
        return p;
    }
};
int main()
{
    dummy *d = new dummy;
    screen s(d);
    cout<<s->p;
    delete d;
}

Stanley 所说的"递归"只是将运算符应用于每个返回的对象,直到返回的类型是指针。

第一次尝试时会发生这种情况:screen::operator ->返回一个指针。因此,这是编译器尝试的对operator ->的最后一次调用。然后,它通过查找返回的 pointee 类型 (dummy( 中具有该名称的成员来解析运算符 (p( 的右键。

实质上,每当编译器在代码中找到语法aᵢ->b时,它基本上应用以下算法:

  1. aᵢ是指针类型吗?如果是这样,请解析*aᵢ的成员b并调用 (*aᵢ).b
  2. 否则,请尝试解决aᵢ::operator ->
    1. 成功后,设置aᵢ₊₁ = aᵢ::operator ->()。转到 1.
    2. 失败时,发出编译错误。

我很难想出一个简短而有意义的例子,其中operator ->调用甚至有意义。可能唯一真正的用途是编写智能指针类时。

但是,下面的玩具示例至少编译并生成了一个数字。但我不建议实际编写这样的代码。它打破了封装,让小猫哭泣。

#include <iostream>
struct size {
    int width;
    int height;
    size() : width(640), height(480) { }
};
struct metrics {
    size s;
    size const* operator ->() const {
        return &s;
    }
};
struct screen {
    metrics m;
    metrics operator ->() const {
        return m;
    }
};
int main() {
    screen s;
    std::cout << s->width << "n";
}

C++ Primer(第5版(在第570页中表述如下:

箭头运算符永远不会失去其成员访问的基本含义。当我们重载箭头时,我们更改箭头从中获取指定成员的对象。我们无法改变箭头获取成员的事实。

一旦screen::operator->()返回指针 ( dummy* (,递归就会停止,因为内置(默认(->在该指针上使用。如果你想要递归,你应该从screen::operator->()返回dummydummy&