У меня есть два предложения по устранению вызовов виртуальных функций, , если необходимо для производительности. Для иллюстрации предположим, что у вас есть функция, принимающая указатель на функцию в качестве аргумента:
void my_algorithm(int (*func)(...), ...)
{
/* ... */
}
А также предположим, что вы заранее знаете все возможные значения, которые может принимать указатель функции. Например:
my_algorithm(func_1, ...);
//...
my_algorithm(func_2, ...);
Сначала преобразуйте ваш оригинальный my_algorithm () в макрос:
#define MY_ALGORITHM(func, ...) \
{ \
/* ... */ \
}
Затем перепишите my_algorithm () как:
extern int func_1(...);
extern int func_2(...);
void my_algorithm(int (*func)(...), ...)
{
if (func == func_1)
MY_ALGORITHM(func_1, ...)
else if (func == func_2)
MY_ALGORITHM(func_2, ...)
else
assert(0 && "Unexpected function arg to my_algorithm()");
}
Это, конечно, удвоит размер скомпилированного объектного файла. И, на поверхности, он удаляет только один уровень косвенности. Но если func_1 и / или func_2 встроены, вы можете значительно ускориться.
И вы можете даже «пропустить» макросы, как в:
#define HYPOT_Y(x) hypot(x, y)
MY_ALGORITHM(HYPOT_Y, ...); //assumes y is known
Второе предложение - это вариант с использованием X Macros (http://en.wikipedia.org/wiki/C_preprocessor#X-Macros). Вместо #define поместите тело исходного my_algorithm () в отдельный файл my_algorithm.h. Затем перепишите my_algorithm () как:
void my_algorithm(int (*func)(...), ...)
{
if (func == func_1)
#define func func_1
#include "my_algorithm.h"
#undef func
else if (func == func_2)
#define func func_2
#include "my_algorithm.h"
#undef func
else
assert(0 && "Unexpected function arg to my_algorithm()");
}
Я бы, вероятно, использовал бы макросы X, если код содержит более пары десятков строк. Его преимущества включают (без каламбура):
- Без уродливых обратных слешей
- Упрощенная отладка (например, обратные трассировки и пошаговое выполнение).
Это все стандартное C. Но скорее старая школа.