11

可能重复:
重载运算符 ->

你好,

我已经看到operator->()它在评估后被链接(重新应用),例如:

struct Bar
{
  Bar() : m_str("Hello world!") {}
  const string* operator->() const { return &m_str; }
  string m_str;
};

struct Foo
{
  const Bar& operator->() const { return m_bar; }
  Bar m_bar;
};

int main()
{
  Foo f;
  cout << f->c_str() << endl;
  return 0;
}

工作得很好,这需要operator->()评估三个 -Foo::operator->()Bar::operator->()常规指针解析。

但它不适用于中间的指针 - 如果Foo::operator->()返回指向 Bar 的指针而不是引用,它将无法编译。例如,同样的情况auto_ptr<auto_ptr<string>>

它是否特定于非重载operator->(),因此它只应用一次并且不会导致链接?是否可以在不使用的情况下使下面的代码工作(*ptr2)-> ...

int main()
{
  string s = "Hello world";
  auto_ptr<string> ptr1(&s);
  auto_ptr<auto_ptr<string> > ptr2(&ptr1);
  cout << ptr1->c_str() << endl; // fine
  cout << ptr2->c_str() << endl; // breaks compilation
}

谢谢!

4

3 回答 3

22

C++98 标准§13.5.6/1“类成员访问”:

如果存在并且如果重载决议机制(13.3)在最佳匹配函数处选择了运算符,则表达式x->m被解释为类型(x.operator->())->m的类对象。xTT::operator->

这在实践中意味着什么x是指针,你不会得到链接。然后,您只需获得内置的operator->(即x->m带有x指针转换为(*x).m)。

但是当x是类类型的对象时T,就可以得到链接的效果。因为那么解释(x.operator->())->m本身(x.operator->())就是某个类的对象,比如 class U。从那里第二个->可以解析为U::operator->,依此类推,如果结果再次是类类型对象......

就像,在你的情况下,Foo::operator->产生(引用)一个 class 的对象Bar,它确实定义了一个operator->.

但是当operator->返回一个指针时,例如std::auto_ptr<T>::operator->,它只是使用的内置指针operator->

顺便说一句,链接用于实际上防止某人delete不当使用。std::auto_ptr不这样做。而且我从未见过它完成。

但是在 [comp.lang.c++.moderated] 中曾经有一个关于如何防止delete智能指针管理的原始指针无意中的长时间讨论线程,这是讨论的一种可能性。

干杯&hth。

于 2011-02-07T16:23:05.760 回答
3

您的第一个示例有效的原因是您返回了引用而不是指针。该运算符通常是无效的,除非它被重载。因此,编译器必须沿链执行重载函数。但是,在实际情况下,auto_ptr您会返回一个真正的指针,并且operator ->会为常规指针调用默认值。

请参阅重载运算符 ->问题以获取更多详细信息。

于 2011-02-07T15:53:34.160 回答
0

不,它不可能工作。如果你可以超载operator ->string *你可以让它工作。但是operator ->已经有了所有指针类型的定义。所以,就像你不能重载+原始数字类型一样,你不能重载operator ->任何指针类型。

即使你可以,编译器怎么知道递归应该何时结束?

于 2011-02-07T15:51:45.950 回答