将指向成员函数的指针传递给父类

passing a pointer to member function to a parent class

提问人:Ori Tsachi 提问时间:8/14/2023 最后编辑:Ori Tsachi 更新时间:8/14/2023 访问量:76

问:

我有一个类,它派生自另一个实现回调函数映射的类 我需要将指向从子项到父项的回调指针传递给父项,但我收到编译转换错误 我试图了解这样做的正确方法是什么......

这是我的课程

class handler
{
public:
    handler(){}
    using Callback = std::function<void(const string&, const string&)>;
    void AddTopicCallbackPair(const string& _st ,Callback _cb)
    {
        m_callbackDictionary.insert(std::make_pair(_st, _cb));
    }
private:
    std::map<const string&, Callback> m_callbackDictionary;
};

我通过这个类继承了这个类

class specificHandler : public handler
{
public:
    specificHandler()
    {
        AddTopicCallbackPair("/root/dev/", std::bind(callback1,this));
    }
    void callback1(const string& _topic, const string& _jsonData);
    void callback2(const string& _topic, const string& _jsonData);
    
private:
}

我想过使用这样的东西

class Handler 
{
.....
template <typename T>
using Callback = void(T::*)(const string&, const string&)
.....
}

然后在 specificHandler 中:

Callback f = &specificHandler::callback1;
AddTopicCallbackPair("/root/dev/", std::bind(callback1,this));

但它对我不起作用,我遇到了编译错误:

error: cannot convert 'void (specificHandler::*)(const string&, const string&)' {aka 'void (specificHandler::*)(const std::__cxx11::basic_string<char>&, const std::__cxx11::basic_string<char>&)'} to 'handler::CallbackFunc' {aka 'void (handler::*)(const std::__cxx11::basic_string<char>&, const std::__cxx11::basic_string<char>&)'} in initialization
   21 |     CallbackFunc f = &specificHandler::callback1;
C++ 继承 std

评论

2赞 Some programmer dude 8/14/2023
Callback或?请尝试向我们展示一个失败代码的适当最小可重现示例CallbackFunc
0赞 pptaszni 8/14/2023
VTC错别字没有错Callback cb = std::bind(&Foo::callback1, this, _1, _2);
0赞 Red.Wave 8/14/2023
答案中已经提到了(优化的)lambda 方法。我只是指出,当您不需要重新排序参数并且不需要占位符时,这是首选项。srd::bind_front(&callback1, this)

答:

2赞 JeJo 8/14/2023 #1

由于需要具体类型,因此使用模板类型别名不是一个好主意。事实上,你在这里不需要它。m_callbackDictionary

我会在这里建议 lambda 函数std::bind

class specificHandler : public handler
{
public:
    specificHandler()
    {
        AddTopicCallbackPair("/root/dev/", 
            [this](const std::string& _topic, const std::string& _jsonData) 
            { return this->callback1(_topic, _jsonData);  });
    }
    
    // ....code
};

现场演示

此外,在类中将键类型更改为非常量引用类型。std::maphandler

否则,它将在实例化 的成员函数时出现问题,其中函数重载,将 作为转发引用和 .std::mapkey_typeconst-&

class handler
{
public:
    using Callback = std::function<void(const std::string&, const std::string&)>;
    void AddTopicCallbackPair(std::string _st, Callback _cb)
    {
        m_callbackDictionary.emplace(std::move(_st), _cb);
        // construct in-place ^~~~~~~ using std::map::emplace
    }

private: 
    std::map<std::string, Callback> m_callbackDictionary;
    //       ^~~~~~~~~~~ non-const ref
};
0赞 Jarod42 8/14/2023 #2

std::bind 需要 std::p laceholders::_1 当您需要使用参数调用它时。

所以会是这样

using namespace std::placeholders;
//...
std::bind(&Foo::callback1, this, _1, _2)

您的语法适用于 std::bind_front (C++20)

std::bind_front(&Foo::callback1, this)

作为替代方案,仍然有 lambda:

[this](const std::string& topic, const std::string& data){ this->Foo::callback1(topic, data); )