Разве это не возможно в CPP?
Строго говоря, нет, из-за безопасности типов и других правил, регулирующих прототипы функций. Однако, в зависимости от ваших потребностей, этот код C может быть перенесен на C ++.
Во-первых, следует отметить, что сигнатура функции void* fn();
в C не одинакова в C ++. В C ++, чтобы получить ту же сигнатуру функции, вам нужно ввести переменные-аргументы примерно так: void* fn(...);
, однако следует отметить, что вы не можете получить доступ к переменным-аргументам переносимым образом для такой сигнатуры функции.
В C ++ void* fn();
- это то же самое, что и void* fn(void);
в C. Для этого, если бы ваши функции имели переменные входы в C, вам нужно было бы проделать небольшую дополнительную работу в C ++, используя список переменных аргументов.
Например, если ваш код был чем-то похожим на следующий код C:
#include <stdio.h>
#define NUM_STEPS 3
static void* filterEvenFoos(void)
{
printf("42\n");
return NULL;
}
static void* timesFooByTwo(int val)
{
printf("%d\n", (val * 2));
return NULL;
}
static void* mapFooToBar(double obj1, size_t obj2)
{
printf("foo(%f)->bar(%zu)\n", obj1, obj2);
return NULL;
}
int main(void)
{
void* (*functionSteps[NUM_STEPS])();
functionSteps[0] = (void*)filterEvenFoos;
functionSteps[1] = (void*)timesFooByTwo;
functionSteps[2] = (void*)mapFooToBar;
functionSteps[0]();
functionSteps[1](42);
functionSteps[2](3.14, &main);
return 0;
}
Вы можете портировать его на C ++ разными способами, но вы можете использовать функциональность va_arg
для получения переменных входных данных, например:
#include <iostream>
#include <cstdarg>
#include <vector>
static void* filterEvenFoos(int na, ...)
{
std::cout << 42 << std::endl;
return NULL;
}
static void* timesFooByTwo(int na, ...)
{
va_list vl;
va_start(vl, na);
std::cout << ((va_arg(vl, int)) * 2) << std::endl;
va_end(vl);
return NULL;
}
static void* mapFooToBar(int na, ...)
{
va_list vl;
va_start(vl, na);
double obj1 = va_arg(vl, double);
size_t obj2 = va_arg(vl, size_t);
std::cout << "foo(" << obj1 << ")->bar(" << obj2 << ")" << std::endl;
va_end(vl);
return NULL;
}
int main(int argc, char* argv[])
{
std::vector<void* (*)(int, ...)> functionSteps;
functionSteps.push_back(&filterEvenFoos);
functionSteps.push_back(×FooByTwo);
functionSteps.push_back(&mapFooToBar);
functionSteps[0](0);
functionSteps[1](0, 42);
functionSteps[2](0, 3.14, &main);
return 0;
}
Вы могли бы заметить, что сигнатура функции немного меняется, чтобы предоставить переносимый способ доступа к аргументам переменной в каждой функции.
Если вы используете C ++ 11, вы также можете использовать std::function
внутри vector
, но вам все равно нужно иметь соответствующие сигнатуры функций .
Вы также можете использовать классы и наследование или специализации шаблонов, но в вашем сценарии это может быть чрезмерным перебором.
В конце концов, это не прямой порт из кода C в C ++, но это выполнимо.
Надеюсь, что это может помочь.