以下代码摘自:https://github.com/facebook/folly/blob/master/folly/Synchronized.h
我最近看了一下Folly库,发现了一些有趣的东西。请考虑以下示例:
#include <iostream>
struct Lock {
void lock() {
std::cout << "Locking" << std::endl;
}
void unlock() {
std::cout << "Unlocking" << std::endl;
}
};
template <class T, class Mutex = Lock >
struct Synchronized {
struct LockedPtr {
explicit LockedPtr(Synchronized* parent) : p(parent) {
p->m.lock();
}
~LockedPtr() {
p->m.unlock();
}
T* operator->() {
std::cout << "second" << std::endl;
return &p->t;
}
private:
Synchronized* p;
};
LockedPtr operator->() {
std::cout << "first" << std::endl;
return LockedPtr(this);
}
private:
T t;
mutable Mutex m;
};
struct Foo {
void a() {
std::cout << "a" << std::endl;
}
};
int main(int argc, const char *argv[])
{
Synchronized<Foo> foo;
foo->a();
return 0;
}
输出结果为:
first
Locking
second
a
Unlocking
我的问题是:为什么这段代码有效?这种模式有名字吗?
- &gt;运算符被调用两次,但它只写了一次。
答案 0 :(得分:12)
因为那是标准所说的:
1)
operator->
应为非静态成员函数,否则为 参数。它使用-> postfix-expression -> id-expression
实现类成员访问解释表达式x->m
对于类型为(x.operator->())->m
的类对象x
,为T
if 如果运营商被选为最佳运营商,则存在T::operator->()
通过重载解析机制匹配函数(13.3)。
(强调我的)
在您的情况下,x
为foo
而m
为a()
,现在,Synchronized
重载operator->
,foo->a()
相当于:
(foo.operator->())->a();
foo.operator->()
是您在课程Synchronized
中的重载,它会返回LockedPtr
,然后LockedPtr
会调用自己的operator->
。
答案 1 :(得分:0)
问问自己:它怎么可能表现出来?
请记住,重载operator->
的重点是智能指针类可以使用与原始指针相同的语法。也就是说,如果你有:
struct S
{
T m;
};
并且指针p
指向S
,然后您通过S::m
访问p->m
,无论p
是S*
还是一些pointer_class<S>
类型。
使用->
和直接调用operator->
之间也存在差异:
pointer_class<S> pointerObj;
S* p = pointerObj.operator->();
请注意,如果使用重载->
并未自动降低额外级别,那么p->m
可能意味着什么?如何使用过载?