3

当与类的成员函数指针的处理,我们可以调用一个函数的对象实例的语法如下:调用一个成员函数指针的智能指针

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()时的行为)

+0

为什么' - > *'为非指针值会做什么?编译器不知道'unique_ptr'试图模仿原始指针。 'operator - > *'是可重载的,但是干净地实现它却很烦人。 – Xeo 2013-03-25 12:30:11

+0

@Xeo我的意思是,标准可以很好地定义' - > *'的默认行为,即“调用'operator->'”返回的对象上的成员指针,如下所示:'operator - > *(memptr){return((* this) - >)。* memptr(); }'。但是由于它不*这样做,为什么C++ 11中的指针类型没有定义这个运算符?有理由吗? – leemes 2013-03-25 12:31:57

+0

嗯,我想这也适用于C++ 03。 – leemes 2013-03-25 12:33:49

回答

3

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

编译器正确拒绝语法。没有operator->*不应该叫operator->(根据标准)。请注意,虽然语法可能看起来类似,但->*本身就是一个运营商,而不是->与其他一些*东西的组成。

+0

到目前为止这么好。我刚刚了解到这一点,谢谢! :)但是:如何一致地解决这个问题?假设我有一个模板参数'T',它既可以是一个原始指针,也可以是一个智能指针,'t'是该实例的一个实例,'f'是指向't'的指针。我现在写'((* t)。* f)()'这很丑,但似乎工作。 – leemes 2013-03-25 12:42:03

+0

@lemes:'auto&obj = * p; (obj。* f)(stuff ...)' – Xeo 2013-03-25 12:43:06

+0

@Xeo这是一样的,不是吗? (比方说,我只需要这个单一表达式的解除引用对象。) – leemes 2013-03-25 12:44:08

0

您可以为智能指针重载operator->*。见Scott Meyers的文章this。其基本思想是返回一个函数对象,该对象在从操作员返回后将被调用。

该文章有点过时了,您现在可以使用变量函数参数编号的一个可变参数模板。

+0

我不能重载现有的智能指针实现的操作符... – leemes 2015-12-11 08:55:57

+0

当然你可以!你只需要在课堂外定义它。例如,对于unique_ptr,代码将如下所示: 'template const PMFC 运算符 - > *(const std :: unique_ptr &pObj,ReturnType(T :: * pmf)()) { \t return std :: make_pair(pObj.get(),pmf); }' – 2015-12-14 16:39:59