2013-08-11 2 views
3

Скажем, у меня есть 2 классов:Как использовать полиморфизм с помощью std :: function?

class A {} 

class B : public A {} 

И я хочу использовать std::function получает что-нибудь типа , но с правопреемником к нему методов, которые получают классы, которые наследуют от (как B).

void myFun(B bbbb) {} 

std::function<void(A)> blah = std::bind(myFun, _1); 

Это, очевидно, не работает, потому что компилятор не будет просто неактуально опущен.

Но как я могу сделать что-то подобное? В основном я хочу провести карту некоторого базового типа std :: function, и в каждом отображаемом значении он будет содержать std::function для производного типа, такого как B.

Есть ли способ привязать оператора литья к заполнителю?

+0

Поскольку не все 'A' гарантированы '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' – Dave

+0

@Dave Это правда, но допустим, что отображение корректно, и оно всегда будет иметь нужный тип. –

+0

Если это так, почему бы вам просто не сделать 'std :: function' взять тип' B'? Если это сложнее, возможно, вы должны его создать? – Dave

ответ

3

ОК, ну, я только что сделал обходной путь в конце.
Компилятор не позволит вам утаивать неявно, поэтому я привязал метод литья.
Таким образом, чтобы держать это все общие и шаблонный, это выглядит следующим образом:

Во-первых, вспомогательный класс для получения типа аргумента функции:

template <typename T> 
class GetFunctionArgumentVal; 

template <class T, typename U > 
class GetFunctionArgumentVal<std::function<U(T)>> 
{ 
public: 
    typedef T arg; 
    typedef U returnVal; 
}; 

Затем оператор приведения, который слепков с помощью static_cast (сохраняет компилировать типобезопасность времени), а затем вызывает функцию с производным классом: например

template <typename FUNCTION, typename BASE> 
void castAndCall(FUNCTION bf, BASE& temp) 
{ 
    bf(static_cast< GetFunctionArgumentVal<FUNCTION>::arg >(temp)); 
} 

использования:

class A {}; 

class B : public A {}; 

class C : public A {}; 

void targetB(B& temp) 
{ 

} 

void targetC(C& temp) 
{ 

} 

    std::function<void(A &)> af; 
    std::function<void(B &)> bf = targetB; 
    std::function<void(C &)> cf = targetC; 

    B b; 
    C c; 

    af = std::bind(castAndCall<decltype(bf),A>,bf,std::placeholders::_1); 
    af(b); 

    af = std::bind(castAndCall<decltype(cf),A>,cf,std::placeholders::_1); 
    af(c); 
Смежные вопросы