You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将接收Derived&的函数存入std::function<void(Base&)>类型的vector?

问题描述

我希望利用多态特性,创建一个存储std::function<void(Base&)>类型对象的vector,该类型函数接收基类Base的引用作为参数;但现在需要向这个vector中存入签名为接收派生类Derived引用的std::function对象。以下是我的代码示例,目前尝试的几种存入方式均编译报错,请问正确的存入方式是什么?

#include <functional>
#include <vector>
#include <stdio.h>

class Base
{
public:
    virtual ~Base() = default;
};

class Derived : public Base
{
public:
    Derived(int x, int y) : a(x), b(y) {}
    int a, b;
};

void DerivedFunction(Derived& d)
{
    printf("A: %d, B: %d\n", d.a, d.b);
}

using FunctionSignature = std::function<void(Base&)>; // 改成Derived&就能正常编译
static std::vector<FunctionSignature> myVector;

int main()
{
    FunctionSignature fn = [](Derived& d){ printf("A: %d, B: %d\n", d.a, d.b); };
    
    myVector.push_back(fn); // 编译错误
    myVector.push_back(std::forward<FunctionSignature>(fn)); // 编译错误
    myVector.push_back(std::bind(&DerivedFunction, std::placeholders::_1)); // 编译错误
    return 0;
}
解决方案

核心问题在于:std::function<void(Base&)>要求能接收任意Base&类型的参数,但你的函数/lambda只接受Derived&——如果直接转换,当传入一个非Derived的Base子类对象时,会导致类型转换错误,所以编译器拒绝这种不安全的隐式转换。

要解决这个问题,需要在包装函数里添加类型检查或安全的向下转换,确保传入的Base&确实是Derived&,再调用目标函数。

方法1:使用dynamic_cast做安全转换(推荐)

在lambda里先尝试把Base&转换成Derived&,转换失败时会抛出std::bad_cast异常,可根据需求处理错误:

// 正确的lambda包装方式
FunctionSignature safeFn = [](Base& b) {
    Derived& d = dynamic_cast<Derived&>(b);
    printf("A: %d, B: %d\n", d.a, d.b);
};

myVector.push_back(safeFn);

方法2:使用static_cast(仅当能保证传入参数一定是Derived对象时)

如果你能确保所有调用该vector中函数时,传入的参数必然是Derived类型对象,可以用static_cast——但这种方式不安全,若转换错误会导致未定义行为:

FunctionSignature unsafeFn = [](Base& b) {
    Derived& d = static_cast<Derived&>(b);
    printf("A: %d, B: %d\n", d.a, d.b);
};

myVector.push_back(unsafeFn);

方法3:包装std::bind的结果

对于DerivedFunction,同样需要先转换参数类型再调用:

myVector.push_back([](Base& b) {
    Derived& d = dynamic_cast<Derived&>(b);
    DerivedFunction(d);
});

原代码报错原因

  • 你的lambda签名是void(Derived&),但FunctionSignature要求void(Base&),两种签名不兼容:Base&不能隐式转换成Derived&(向下转换需要显式操作)。
  • std::bind的结果无法直接转换成std::function<void(Base&),因为绑定的函数期望Derived&,而std::function会传入Base&,类型不匹配。

内容的提问来源于stack exchange,提问作者avilapa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 21:50:38