toa*_*fan 6 c++ member-function-pointers smart-pointers unique-ptr c++11
我正在尝试member-function使用智能指针实例执行类的。该函数的地址通过值传递,我想通过相应类的智能指针实例调用该值。
我已经试过了:
(registerList.*setRegister)();
Run Code Online (Sandbox Code Playgroud)
但是它出错了:
no match for ‘operator->*
Run Code Online (Sandbox Code Playgroud)
Register 类成员函数:
uint16_t Registers::getSP()
{
return this->sp;
}
Run Code Online (Sandbox Code Playgroud)
代码段:
std::unique_ptr<Registers> registerList;
SetRegisteropcodeLdWordRegister(&Registers::getSP)
void opcodeLdWordRegister(uint16_t (*Registers::setRegister)())
{
(registerList.*setRegister)();
}
Run Code Online (Sandbox Code Playgroud)
首先,您显示的代码和错误消息不匹配。对于给定的代码,您应该(从 clang)获得以下错误消息
error: left hand operand to .* must be a class compatible with the right hand operand, but is 'std::unique_ptr<Registers>'
(registerList.*setRegister)();
^
Run Code Online (Sandbox Code Playgroud)
这可以通过取消引用指针来解决(如@Caleth 的回答):
((*registerList).*setRegister)();
Run Code Online (Sandbox Code Playgroud)
现在问题中显示的错误消息:no match for ‘operator->*当您尝试以下语法时应该会出现。(最小可重现代码)
(registerList->*setRegister)();
Run Code Online (Sandbox Code Playgroud)
这是因为智能指针没有标准中定义的指针成员访问运算符。因此,您需要operator*通过成员函数或通过成员函数取消引用智能指针std::unique_ptr::get,并调用成员函数。
使用成员std::unique_ptr::get的正确语法是(参见在线演示)
(registerList.get()->*setRegister)()
Run Code Online (Sandbox Code Playgroud)
话虽如此,如果您可以访问c++17,请使用统一版本的函数调用程序std::invoke来调用具有相应实例的成员函数,这样您就可以忘记operator->*.
您的代码也有几个问题:
你的成员函数指针类型opcodeLdWordRegister是错误的。应该是
error: left hand operand to .* must be a class compatible with the right hand operand, but is 'std::unique_ptr<Registers>'
(registerList.*setRegister)();
^
Run Code Online (Sandbox Code Playgroud)
以下是固定版本。
((*registerList).*setRegister)();
Run Code Online (Sandbox Code Playgroud)registerList指针将导致 UB。以下是为案件的示范性最小的完整的例子:(见现场演示在线)
#include <iostream>
#include <functional> // std::invoke
#include <memory> // std::unique_ptr
class Registers
{
uint16_t sp{2}; // member initialized with 2
public:
uint16_t getSP() const // function can be marked const as it does not alter the member
{
return this->sp;
}
};
auto registerList = std::make_unique<Registers>(); // initialized the pointer with default object
void opcodeLdWordRegister(uint16_t(Registers::*setRegister)() const)
// ^^^^^^^^^^^^^^^^^^^^^^^^^ correct syntax
{
std::cout << std::invoke(setRegister, registerList);
}
int main()
{
opcodeLdWordRegister(&Registers::getSP);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
2
Run Code Online (Sandbox Code Playgroud)