据说箭头运算符是递归应用的。但是当我尝试执行以下代码时,它会在打印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;
}
答案 0 :(得分:11)
Stanley所说的“递归”只是将运算符应用于每个返回的对象,直到返回的类型为指针。
首次尝试时会发生这种情况:screen::operator ->
返回一个指针。因此,这是编译器尝试的operator ->
的最后一次调用。然后通过在返回的指针类型(p
)中查找具有该名称的成员来解析运算符(dummy
)的右手。
基本上,只要编译器在代码中找到语法aᵢ->b
,它就基本上应用以下算法:
aᵢ
吗?如果是,请解析b
的成员*aᵢ
并致电(*aᵢ).b
。aᵢ::operator ->
aᵢ₊₁ = aᵢ::operator ->()
。转到1。我很难想出一个简短而有意义的例子,其中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->()