c++ - 将 std::function<void(Derived*)> 转换为 std::function<void(Base*)>

标签 c++ c++11 std-function

首先,我定义了两个类,它们相互继承。

class A {
};
class B : public A {
};

然后,我声明一个使用 std::function<void(A*)> 的函数:

void useCallback(std::function<void(A*)> myCallback);

最后,我收到了 std::function与我想在回调函数中使用的其他地方不同(但理论上兼容)的类型:

std::function<void(B*)> thisIsAGivenFunction;

useCallback(thisIsAGivenFunction);

我的编译器 (clang++) 拒绝这样做,因为 thisIsAGivenFunction 的类型与预期的类型不匹配。但与 B继承自 A ,这对 thisIsAGivenFunction 是有意义的可以接受。

应该吗?如果不是,为什么?如果应该,那我做错了什么?

最佳答案

假设您的类层次结构更大一点:

struct A { int a; };
struct B : A { int b; };
struct C : A { int c; };

你有如下功能:

void takeA(A* ptr)
{
    ptr->a = 1;
}

void takeB(B* ptr)
{
    ptr->b = 2;
}

有了这个,我们可以说takeA可调用的,可以使用派生自A 的任何类实例(或 A 本身),以及 takeB调用类的任何实例B :

takeA(new A);
takeA(new B);
takeA(new C);

takeB(new B);
// takeB(new A); // error! can't convert from A* to B*
// takeB(new C); // error! can't convert from C* to B*

现在,std::function也就是说,它是可调用对象的包装器。它不太关心存储的函数对象的签名只要该对象是可调用其参数std::function包装:

std::function<void(A*)> a; // can store anything that is callable with A*
std::function<void(B*)> b; // can store anything that is callable with B*

您要做的是转换 std::function<void(B*)>std::function<void(A*)> .换句话说,您想要存储可调用对象,采用 B*在函数的包装类中使用 A* .是否存在 A* 的隐式转换至B* ?不,没有。

也就是说,也可以调用std::function<void(A*)>带有一个指向类 C 实例的指针:

std::function<void(A*)> a = &takeA;
a(new C); // valid! C* is forwarded to takeA, takeA is callable with C*

如果 std::function<void(A*)>是否可以包装一个可调用对象的实例,只取B* ,您希望它如何与 C* 一起工作? ?:

std::function<void(B*)> b = &takeB;
std::function<void(A*)> a = b;
a(new C); // ooops, takeB tries to access ptr->b field, that C class doesn't have!

幸运的是,上面的代码没有编译。

不过,反之亦然:

std::function<void(A*)> a = &takeA;
std::function<void(B*)> b = a;
b(new B); // ok, interface is narrowed to B*, but takeA is still callable with B*

关于c++ - 将 std::function<void(Derived*)> 转换为 std::function<void(Base*)>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26403556/

相关文章:

c++ - 如何找到 C++ 标准的修订版,其中删除或更改了特定要求?

c++ - 随着数字变大,c++ 中的 std::sqrt 函数会变慢吗?

c++ - ICU UnicodeString 到 Locale 编码

c++ - 对于按值传递的重成员,构造函数的初始化列表中真的需要 std::move 吗?

c++ - 如何找到继承类的分配地址

c++ - 如何在不提供有效生成器的情况下告诉 boost::karma::rule 不消耗其属性?

c++ - 使用 std::function 在对象列表上调用任何对象成员函数

c++ - 为什么 libc++ 的 shared_ptr 实现使用完整的内存屏障而不是放松的?

c++ - Q : std::function 在同一个数组中有不同的类型

c++ - std::function 性能与模板相比