可能重复:
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
}
谢谢!
答案 0 :(得分:19)
C ++ 98标准§13.5.6/ 1“类成员访问”:
如果
x->m
存在且操作符被选中,则(x.operator->())->m
类型x
的类T
被解释为T::operator->
通过重载解析机制匹配函数(13.3)。
这在实践中意味着当x
是指针时,你不会被链接;然后,您只需获取内置operator->
(即x->m
,x
指针转换为(*x).m
。)
但是当x
是类类型T
的对象时,则可以获得链接效果。因为那时解释为(x.operator->())->m
可以是(x.operator->())
本身是某个类的对象,比如类U
。第二个->
可以解析为U::operator->
,依此类推,如果其结果再次是类类型对象......
就像你的情况一样,Foo::operator->
生成(引用)类Bar
的对象,它确实定义了operator->
。
但是当operator->
返回指针时,例如std::auto_ptr<T>::operator->
确实如此,那就是使用的内置operator->
。
顺便说一句,链接可以用于实际阻止某人不恰当地使用delete
。 std::auto_ptr
不这样做。我从来没有见过它。
但是[comp.lang.c ++。moderated]中曾经有过一个长时间的讨论线程,关于如何防止由智能指针管理的原始指针的无意delete
,这是讨论的一种可能性
干杯&amp;第h
答案 1 :(得分:3)
第一个示例的工作原因是因为您返回了引用而不是指针。该运算符通常无效,除非它过载。因此,编译器必须在链中执行重载函数。但是,在auto_ptr
的情况下,实际上会返回一个真正的指针,并且会为常规指针调用默认的operator ->
。
有关详细信息,请参阅Overloading operator ->问题。
答案 2 :(得分:0)
不,它不可能工作。如果您可以为operator ->
重载string *
,那么您可以使其正常工作。但是operator ->
已经有了所有指针类型的定义。因此,就像您不能为原始数字类型重载+
一样,您不能为任何指针类型重载operator ->
。
即使你可以,编译器怎么知道递归何时应该结束?