如何利用继承实现通用回调函数指针?解决std::function转换报错
问题原因
std::function<void(A*)> 和 std::function<void(A1*)> 是完全不同的类型,且出于类型安全考虑,后者无法隐式转换为前者——registerCallback 可能会传入 A2*、A3* 这类非 A1* 的指针,而你的回调函数仅能处理 A1*,直接转换会导致类型错误。
解决方案
方案一:包装回调函数,添加类型检查
将原回调包装成接受 A* 的函数,通过 dynamic_cast 验证指针类型后再执行逻辑,既保证类型安全,又适配 registerCallback 的参数要求:
int main() { std::function<void(A1*)> fptr = [&](A1*) { cout << "dummy" << endl; }; // 包装后传入 registerCallback([&](A* a) { if (A1* a1 = dynamic_cast<A1*>(a)) { fptr(a1); } }); }
方案二:将 registerCallback 改为模板函数
如果希望函数能接受任意派生类的回调,可以把它改成模板函数,自动推导参数类型:
#include <type_traits> template<typename T> void registerCallback(std::function<void(T*)> func_ptr) { // 静态断言确保T是A的派生类,避免非法类型传入 static_assert(std::is_base_of_v<A, T>, "T must be a derived class of A"); // 后续业务逻辑 } int main() { std::function<void(A1*)> fptr = [&](A1*) { cout << "dummy" << endl; }; registerCallback(fptr); // 模板自动推导T为A1,无报错 }
方案三:直接传递适配后的Lambda
如果不需要提前保存 fptr,可以直接编写接受 A* 的Lambda,省去中间的 std::function 存储步骤:
int main() { registerCallback([&](A* a) { if (auto a1 = dynamic_cast<A1*>(a)) { cout << "dummy" << endl; } }); }
内容的提问来源于stack exchange,提问作者user3443615
相关产品推荐
相关产品推荐

