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

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

本文关键字:std 分隔 function 调用 变量 类方法 派生 C++ 范围 实例 绑定      更新时间:2023-10-16

考虑拥有一个由多个子类继承的基类。

是否可以绑定它的一些方法来创建可以直接调用而不是从继承的类实例调用的函数。

以下示例应强调这种情况:


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); 
...
}

但是,由于以下错误,它无法编译:

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

也许任何人都可以帮我修复它?

您需要为参数使用占位符。我还会从第二个参数中删除引用,因为您已经有一个指针,并且传递对指针的引用将传入指针的地址,这不是您想要的。

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

希望这有帮助。

您的代码存在一些问题。

  • 您需要公开这些方法
  • void main()来自预标准化的时代,但它在代码C++无效。你需要int main()
  • 不要使用具有所有权的原始指针。 使用智能指针。
  • 不要使用std::bind.使用λ。他们在各个方面都更胜一筹。

为了不让所有更改使你过载,让我们使用 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);
}

现在是带有智能指针的变体。如果你的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);
}

否则您需要使用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);
}

此外,如果您不需要std::function的类型擦除,您应该制作f1f2lambda。 例如auto f1 = [=] ...