首先,我定义了两个类,它们相互继承。
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/