То, что вы хотите, это ковариантные типы аргументов .Это не поддерживается в C ++, потому что это нарушает безопасность типов.Чтобы лучше понять это, давайте рассмотрим простой пример:
struct Vehicle {};
struct Tricycle : Vehicle {};
struct Tank : Vehicle {};
void drive(Vehicle const & b) { ... }
void giveToChild(Tricycle const & b) { ... }
Здесь мы имеем простую иерархию типов, а также две функции, ссылающиеся соответственно на базовый класс и один из производного класса.Теперь, если то, что вы просили, было разрешено, мы могли бы сделать следующее:
typedef void (*funcPtr)(Vehicle const &);
funcPtr = &giveToChild; // this is not allowed
funcPtr(Tank()); // oops, I just gave a tank to my child!
Язык мог бы реализовать некоторую проверку типов во время выполнения, но это не так, как работает C ++.Однако обратное преобразование (контравариантность) может быть разрешено без каких-либо проблем (на самом деле, делегаты C # допускают это), но это невозможно в C ++ по некоторым причинам, о которых я не знаю.Вот пример того, что было бы разрешено:
typedef void (*funcPtr)(Tricycle const &);
funcPtr = &drive; // this could be allowed, but is not (in C++)
funcPtr(Tricycle()); // I can only drive a tricycle, but that's ok since it's a
// vehicle and I know how to drive all vehicles
Таким образом, в принципе, то, что вы пытаетесь достичь, невозможно без обращения к функциям пересылки, которые проверяют тип аргументов перед вызовом исходных функций:
void forwardFN(Foo * f)
{
FooN * instance = dynamic_cast<FooN *>(f);
if (instance) fN(instance);
else throw type_exception();
}