递归应用运算符 - >

时间:2012-05-05 09:48:36

标签: c++

据说箭头运算符是递归应用的。但是当我尝试执行以下代码时,它会在打印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;
}

3 个答案:

答案 0 :(得分:11)

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

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

基本上,只要编译器在代码中找到语法aᵢ->b,它就基本上应用以下算法:

  1. 指针类型是aᵢ吗?如果是,请解析b的成员*aᵢ并致电(*aᵢ).b
  2. 否则,请尝试解决aᵢ::operator ->
    1. 成功时,设置aᵢ₊₁ = aᵢ::operator ->()。转到1。
    2. 失败时,发出编译错误。
  3. 我很难想出一个简短而有意义的例子,其中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";
    }
    

答案 1 :(得分:2)

C ++ Primer (第5版)在第570页将其公式化如下:

  

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

答案 2 :(得分:0)

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

返回dummy&screen::operator->()