首页 > 解决方案 > 如何使用智能指针对象执行成员函数指针?

问题描述

我正在尝试member-function使用智能指针实例执行一个类。这个函数的地址是按值传递的,我想通过相应类的智能指针实例来调用它。

我已经尝试过了:

(registerList.*setRegister)();

但它出错了:

no match for ‘operator->*

Register类成员函数:

uint16_t Registers::getSP()
{
    return this->sp;
}

代码片段:

std::unique_ptr<Registers> registerList;

SetRegisteropcodeLdWordRegister(&Registers::getSP)

void opcodeLdWordRegister(uint16_t (*Registers::setRegister)()) 
{
        (registerList.*setRegister)();
}

标签: c++c++11smart-pointersunique-ptrmember-function-pointers

解决方案


首先,您显示的代码和错误消息不匹配。对于给定的代码,您应该(从 clang)收到以下错误消息

error: left hand operand to .* must be a class compatible with the right hand operand, but is 'std::unique_ptr<Registers>'    
   (registerList.*setRegister)();
            ^

这可以通过取消引用指针来解决(就像在@Caleth's answer中一样):

((*registerList).*setRegister)();

现在问题中显示的错误消息:no match for ‘operator->*应该在您尝试以下语法时出现。(最小可重现代码

(registerList->*setRegister)();

这是因为智能指针没有标准中定义的指向成员的访问运算符。因此,您需要operator*通过成员函数或通过成员函数取消引用智能指针std::unique_ptr::get,并调用成员函数。

使用该成员std::unique_ptr::get的正确语法是请参阅在线现场演示

(registerList.get()->*setRegister)()

话虽如此,如果您有权访问 ,请使用统一版本的函数调用std::invoke程序来调用具有相应实例的成员函数,通过它您可以忘记(可能)复杂的operator->*.

您的代码也有几个问题:

  • 您的成员函数指针类型错误。opcodeLdWordRegister应该是

    return_type(Class_name::* variable_name)(/*parameters_types, if any*/)
    

    以下是固定版本。

    #include <functional>  // std::invoke
    
    void opcodeLdWordRegister(uint16_t(Registers:: * setRegister)())
    //                                 ^^^^^^^^^^^^^^^^^^^^^^^^^ >>> correct syntax
    {   
        std::invoke(setRegister, registerList);
        //          ^^^^^^^^^^^                 member function
        //                       ^^^^^^^^^^^^   instance
     }
    
  • 其次,取消引用未初始化的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;
}

输出

2

推荐阅读