假设您的类层次结构更大一些:
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
is callable与派生类的任何实例A
(or A
本身),并且takeB
is callable与类的任何实例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
是,它是一个可调用的包装器对象。它不太关心存储的函数对象的签名只要该物体是callable及其参数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*)>
to std::function<void(A*)>
。换句话说,您想要存储可调用对象B*
在函数的包装类中A*
。是否存在隐式转换A*
to 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*
If std::function<void(A*)>
could wrap可调用对象的实例仅采用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*