让我们假设你的类层次结构是有点大:
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
是可调用与任何实例的cl屁股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++模板多态](http://stackoverflow.com/questions/2203388/c-templates-polymorphism) – Samuel 2014-10-16 11:50:16
它不重复,'std :: function'支持这种*转换*。但换句话说,您可以将'std :: function'转换为'std :: function ',因为在'A *'上运行的函数在接收到'B *'的实例时可以做同样的事情,但是而不是其他方式 –
2014-10-16 11:51:20
问题的根源在于使用'std :: function'作为回调函数,而不是接受'Functor'作为模板参数。除非你有充分的理由这样做,否则不要这样做。 – pmr 2014-10-16 17:28:55