具有多态性的 std::bind 和 std::function,基类

ren*_*ena 3 c++ std

我试图将一个对象绑定到一个函数,但正在调用基类的类函数。代码只是真实代码的一个例子。我只会在后面的实际代码中使用字符串。

 class A {
    public:
        virtual void f(const std::string &s) {
            std::cout << "A " << s << std::endl;
        }
    };

    class B : public A {
    public:
        void f(const std::string &s) override {
            std::cout << "B " << s << std::endl;
        }
    };

    void main() {
        std::unique_ptr<A> a = std::make_unique<B>();

        std::function<void(const std::string &)> callback
                =  std::bind(&A::f, *a, std::placeholders::_1);
        callback("my string");
    }
Run Code Online (Sandbox Code Playgroud)

结果是

 A my string
Run Code Online (Sandbox Code Playgroud)

我试图将其更改为 &B:f,但出现错误。

No viable conversion from 'typename _Bind_helper<__is_socketlike<void (B::*)(const basic_string<char> &)>::value, void (B::*)(const basic_string<char> &), A &, const _Placeholder<1> &>::type' (aka '_Bind<void (Centerity::Cluster::Correlation::B::*(Centerity::Cluster::Correlation::A, std::_Placeholder<1>))(const std::basic_string<char> &)>') to 'std::function<void (const std::string &)>' (aka 'function<void (const basic_string<char> &)>')
Run Code Online (Sandbox Code Playgroud)

我试图将其更改为A* a = B();相同的结果。在任何地方都找不到类似的代码。当然,创建B b会调用B::f,但这对我没有帮助。

我可以失去绑定并使用 lambda,但我不知道如何。

abh*_*ora 7

笔记:

我不知道您使用的是哪个编译器,但main不应为空。我在下面的代码中修复了它:

#include <memory>
#include <iostream>
#include <functional>

class A {
public:
    virtual void f(const std::string &s)
    {
        std::cout << "A " << s << std::endl;
    }
};

class B: public A {
public:
    void f(const std::string &s) override 
    {
        std::cout << "B " << s << std::endl;
    }
};

int main() 
{
    std::unique_ptr<A> a = std::make_unique<B>();
    auto callback = std::bind(&A::f, a.get(), std::placeholders::_1);

    callback("my string");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

B my string
Run Code Online (Sandbox Code Playgroud)

问题是将指向基类的指针(指向派生类的对象)传递给std::bind(&A::f, a.get(), std::placeholders::_1);.

如果按值传递,则将创建基类 A 的新对象(通过复制构造函数),并且将调用基类的 f 版本,如您在程序中所观察到的那样。