5

在处理类成员函数指针时,我们可以使用以下语法调用对象实例上的函数:

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()

4

2 回答 2

3

编译器是否应该拒绝上面的箭头语法?因为通常(当静态调用函数时),它调用操作符->。不应该 ->* 也只是调用运算符 -> 吗?

编译器拒绝语法是正确的。No 不operator->*应该调用operator->(根据标准)。请注意,虽然语法可能看起来相似,但->*is 本身是一个运算符,而不是->with some other * thing的组合。

于 2013-03-25T12:39:24.020 回答
1

您可以重载operator->*for 智能指针。请参阅Scott Meyers 的这篇文章。基本思想是返回一个函数对象,该对象将在运算符返回后被调用。

这篇文章有点过时了,您现在可以只使用一个可变参数模板来表示可变函数参数号。

于 2015-12-10T04:50:02.197 回答