是运营商 - > “链式”指针?

时间:2011-02-07 15:46:48

标签: c++ operator-keyword method-chaining

  

可能重复:
  Overloading operator ->

您好,

我看到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
}

谢谢!

3 个答案:

答案 0 :(得分:19)

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

  

如果x->m存在且操作符被选中,则(x.operator->())->m类型x的类T被解释为T::operator->通过重载解析机制匹配函数(13.3)。

这在实践中意味着当x是指针时,你不会被链接;然后,您只需获取内置operator->(即x->mx指针转换为(*x).m。)

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

就像你的情况一样,Foo::operator->生成(引用)类Bar的对象,它确实定义了operator->

但是当operator->返回指针时,例如std::auto_ptr<T>::operator->确实如此,那就是使用的内置operator->

顺便说一句,链接可以用于实际阻止某人不恰当地使用deletestd::auto_ptr不这样做。我从来没有见过它。

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

干杯&amp;第h

答案 1 :(得分:3)

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

有关详细信息,请参阅Overloading operator ->问题。

答案 2 :(得分:0)

不,它不可能工作。如果您可以为operator ->重载string *,那么您可以使其正常工作。但是operator ->已经有了所有指针类型的定义。因此,就像您不能为原始数字类型重载+一样,您不能为任何指针类型重载operator ->

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