处理类成员函数指针时,我们可以使用以下语法在对象实例上调用函数:
当一个实例有一个原始指针时,语法是这样的:
这很好地遵循了静态函数调用的类比:
我通过先使用解引用运算符,然后使用
struct X {
void foo();
};
X x; // Instance
auto f = &X::foo; // Member function pointer
(x.*f)(); // Call function f on x
当一个实例有一个原始指针时,语法是这样的:
X *xptr = new X();
(xptr->*f)();
这很好地遵循了静态函数调用的类比:
x.foo();
x->foo();
然而,当我拥有该类的一个智能指针时,这不起作用:
unique_ptr<X> xsptr(new X());
(xsptr->*f)(); // g++: error: no match for 'operator->*' in 'xsptr ->* f'
我通过先使用解引用运算符,然后使用
.
语法进行调用来解决这个问题。((*xsptr).*f)();
这有多丑陋?
编译器是否应该拒绝上述的箭头语法?因为通常情况下(在静态调用函数时),它会调用 operator ->
。难道 ->*
也不应该只调用 operator ->
吗?
编译器错误部分回答了这个问题:错误提示表明我们可以重载 operator ->*
以便在取消引用对象后调用成员函数指针,但是 unique_ptr
却没有这样做。但这引发了更多的问题。如果语言要求这样做,为什么智能指针却没有这样做呢?是因为这样做会引入其他问题吗?为什么我们必须编写此运算符,而不是隐式地调用 ->
返回的对象上的成员函数指针呢?(例如,当编写 xsptr->foo()
时的行为)
->*
定义一个默认行为,即“在operator->
返回的对象上调用成员指针”,类似于以下内容:operator ->*(memptr) { return ((*this)->).*memptr(); }
。但由于它 没有 这样做,那么为什么 C++11 中的指针类型没有定义这个运算符呢?有原因吗? - leemescall(xsptr, f, args);
- Peter Woodcall
。 - Peter Wood