简体   繁体   English

在 C++ 中绑定派生类方法从分离的 std::function 变量调用,在实例范围之外

[英]Binding derived class method in C++ to be called from separated std::function variable, outside the scope of the instance

Consider having a base class that is inherited by multiple sub-classes.考虑拥有一个由多个子类继承的基类。

Is it possible to bind some of its methods to create function that can be called directly and not from the inherited class instance.是否可以绑定它的一些方法来创建可以直接调用而不是从继承的类实例调用的函数。

The following example should emphasis the case :下面的例子应该强调这种情况:


class A {
    virtual void method(int a, int b) { ... } 
};

class B : public A {
    virtual void method(int a, int b) { ... }
};
class C : public A {
    virtual void method(int a, int b) { ... }
};


void main () {

    A * a = new B();
    A * aa= new C();

    std::function<void(int,int)> f1 = std::bind(&A::method, &a);
    std::function<void(int,int)> f2 = std::bind(&A::method, &aa);

    f(1,2); 
    f(2,3); 
    ...
}

however, it doesn't compile due to the following error :但是,由于以下错误,它无法编译:

No viable conversion from '__bind<void (A::*)(int, int), A **>' to 'std::function<void (int, int)>'

Perhaps anybody can help me fix it ?也许有人可以帮我修复它?

You need to use placeholders for your arguments.您需要为您的参数使用占位符。 I would also remove the reference from the second argument as you've a pointer already and passing a reference to a pointer would pass in the address of pointer which is not what you want.我还会从第二个参数中删除引用,因为您已经有一个指针,并且传递对指针的引用会传入不是您想要的指针地址。

std::function<void(int,int)> f1 = std::bind(&A::method, a, std::placeholders::_1, std::placeholders::_2);

Hope this helps.希望这可以帮助。

There are a few issues with your code.您的代码存在一些问题。

  • You need to make the methods public您需要公开这些方法
  • void main() comes from a time of pre-standardization, it's not valid C++ code. void main()来自预标准化时期,它不是有效的 C++ 代码。 You need int main()你需要int main()
  • don't use raw pointers that have ownership.不要使用拥有所有权的原始指针。 use smart pointers.使用智能指针。
  • don't use std::bind .不要使用std::bind Use lambdas.使用 lambda。 They are superior in every way.他们在各方面都优越。

In order to not overload you with all the changes, lets do this with lambdas and keep the raw pointers:为了不让您因所有更改而超载,让我们使用 lambda 来执行此操作并保留原始指针:

int main ()
{
    A * a = new B();
    A * aa= new C();

    std::function<void(int,int)> f1 = [=](int p1, int p2) { return a->method(p1, p2); };
    std::function<void(int,int)> f2 = [=](int p1, int p2) { return aa->method(p1, p2); };

    f1(1, 2);
    f2(2, 3);
}

And now a variant with smart pointers.现在是带有智能指针的变体。 If your f1 and f2 don't live beyond a and aa you can do this:如果您的f1f2不超过aaa您可以这样做:

void test()
{
    std::unique_ptr<A> a = std::make_unique<B>();
    std::unique_ptr<A> aa = std::make_unique<C>();

    std::function<void(int,int)> f1 = [ptr = a.get()](int p1, int p2) { return ptr->method(p1, p2); };
    std::function<void(int,int)> f2 = [ptr = aa.get()](int p1, int p2) { return ptr->method(p1, p2); };

    f1(1, 2);
    f2(2, 3);
}

Else you need to use shared_ptr :否则你需要使用shared_ptr

void test_shared()
{
    std::shared_ptr<A> a = std::make_shared<B>();
    std::shared_ptr<A> aa = std::make_shared<C>();

    std::function<void(int,int)> f1 = [=](int p1, int p2) { return a->method(p1, p2); };
    std::function<void(int,int)> f2 = [=](int p1, int p2) { return aa->method(p1, p2); };

    f1(1, 2);
    f2(2, 3);
}

Also if you don't need the type erasure of std::function you should make f1 and f2 lambdas.此外,如果您不需要std::function的类型擦除,您应该制作f1f2 lambdas。 Eg auto f1 = [=] ...例如auto f1 = [=] ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM