Давайте предположим, что ваша иерархия классов немного больше:
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
Это не дубликат, 'std :: function' поддерживает такие * преобразования *. но, наоборот, вы можете преобразовать 'std :: function' в 'std :: function ', потому что функция, которая работает с 'A *', может сделать то же самое, когда получает экземпляр 'B *', но а не наоборот –
Источником вашей проблемы является использование 'std :: function' в качестве обратного вызова вместо принятия« Functor »в качестве аргумента шаблона. Если у вас нет веских оснований для этого, не делайте этого. – pmr