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