Ваша обеспокоенность по поводу void*
вполне обоснована: это неопределенное поведение , потому что (в Intermediate::f
) вы выполняете арифметику указателя и читаете указатель, который не соответствует тип массива.
Хорошая новость заключается в том, что есть простое решение: поскольку ваши массивы должны вызывать функции производного класса, задавая только Base&
и BaseThunk
, вы можете store этот тип:
Base::BaseThunk Derived::steps[]=
{static_cast<BaseThunk>(&Derived::f1),
…};
static_cast
несколько многословны, но совершенно законны, если вы используете результирующих BaseThunk
объектов с объектом, тип которого является производным от Derived
. Вам даже не нужно сначала получать Derived*
:
int Base::execute(BaseThunk x) // no need to be virtual
{return (this->*x)();}