C++ 在智能指针上调用成员函数指针

C++ 在智能指针上调用成员函数指针,c++,c++11,operator-overloading,smart-pointers,member-function-pointers,C++,C++11,Operator Overloading,Smart Pointers,Member Function Pointers,在处理类成员函数指针时,我们可以使用以下语法调用对象实例上的函数: 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)();

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

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'
这有多难看

编译器应该拒绝上面的箭头语法吗?因为通常(静态调用函数时),它调用
操作符->
。你不应该也直接打电话给话务员吗

编译器错误部分地回答了这个问题:错误的意思是我们可以重载
操作符->*
来调用被解除引用的对象上的成员函数指针,而
unique\u ptr
没有。但这带来了更多的问题。如果语言需要,为什么智能指针不这样做呢?它是否打算不这样做,因为它引入了其他问题?为什么我们必须编写这个操作符,而不是隐式调用
->
返回的对象上的成员函数指针?(因为这是编写
xsptr->foo()时的行为)

编译器应该拒绝上面的箭头语法吗?因为通常(静态调用函数时),它调用操作符->。不应该->*也直接打电话给接线员->


编译器拒绝语法是正确的。无
操作员->*
不应呼叫
操作员->
(根据标准)。请注意,虽然语法可能看起来很相似,
->*
本身是一个运算符,而不是
->
与其他
*
的组合

您可以为智能指针重载
运算符->*
。见斯科特·迈尔斯的文章。基本思想是返回一个函数对象,从操作符返回后将调用该函数对象


这篇文章有点过时,因为您现在可以只使用一个变量模板作为变量函数参数编号。

为什么非指针值的
->*
应该做些什么?编译器不知道
unique\u ptr
试图模拟原始指针<代码>运算符->*
是可重载的,但是干净地实现它很烦人。@Xeo我的意思是,标准可以很好地定义
->*
的默认行为,即“调用
运算符->
返回的对象上的成员指针”,如下所示:
运算符->*(memptr){return((*this)->).*memptr();}
。但既然它没有这样做,为什么C++11中的指针类型没有定义此运算符?有什么原因吗?啊,我想这也适用于C++03。现在告诉我如何使用“示例实现”将参数传递给被调用的成员函数:)这也应该告诉你为什么在C++03中它更糟糕-没有完美的转发。封装它,不要再考虑它:
call(xsptr,f,args)是的,到目前为止还不错。我刚学会这个,谢谢!:)但是:如何始终如一地解决这个问题?假设我有一个模板参数
T
,它可以是原始指针,也可以是智能指针,
T
是它的一个实例,而
f
是调用
T
的指针。我目前正在写
((*t)。*f)(
,这很难看,但似乎很管用。@leemes:
auto&obj=*p;(obj.*f)(stuff…
@Xeo哪个是相同的,不是吗?(假设我只需要这个表达式的解引用对象。)@leems:如果它只是这个表达式,你关心什么?另外,在本例中,
std::bind(f,p,stuff…)将变为
(*t)。*f)(stuff…
。@leems:我可以更正,您可以将其作为数据成员的
操作符->*
来实现。我不确定是否可以对非数据成员(即函数成员)执行此操作,因为我无法确定重载的
运算符->*
返回的类型应该是什么(对于指针
U*
和指向成员
tu:*
的指针,返回被定义为
T&
,但对于成员函数,这并不能完全切断它)。当然可以!您只需在类之外定义它。例如,对于unique\ptr,代码类似于:
模板常量PMFC操作符->*(const std::unique_ptr&pObj,ReturnType(T::*pmf)(){return std::make_pair(pObj.get(),pmf);}
((*xsptr).*f)();