> Приносит ли удобство использование функций в качестве объектов в C ++?
Да: механизм шаблонов C ++ допускает все другие стили программирования C / C ++ (стиль C и стиль ООП, см. Ниже).
> Почему мы не можем просто использовать указатель на функцию вместо этого? Есть примеры?
Но мы можем: Простой указатель на функцию C также является объектом с четко определенным оператором ().
Если мы проектируем библиотеку, мы не хотим заставлять кого-либо использовать этот стиль указателя Си, если это не нужно. Обычно это так же нежелательно, как принуждать все / всех быть в / использовать стиль ООП; см. ниже.
С точки зрения C-программистов и функциональных программистов, ООП имеет тенденцию не только быть медленнее, но и более многословным и в большинстве случаев быть неправильным направлением абстракции («информация» не является и не должна быть «объектом»). Из-за этого люди, как правило, путаются, когда слово «объект» используется в других контекстах.
В C ++ все с желаемыми свойствами можно рассматривать как объект. В этом случае простой указатель на функцию C также является объектом. Это не означает, что парадигмы ООП используются, когда это нежелательно; это просто правильный способ использования механизма шаблонов.
Чтобы понять различия в производительности, сравните стили / парадигмы программирования (-языка) и их возможные оптимизации:
C стиль:
- Указатель на функцию с ее замыканием («this» в ООП, указатель на некоторую структуру) в качестве первого параметра.
- Для вызова функции сначала необходимо получить доступ к адресу функции.
- Это 1 косвенное направление; подкладка невозможна.
C ++ (и Java) стиль ООП:
- Ссылка на объект, производный от класса с виртуальными функциями.
- Ссылка на первый указатель.
- Указатель на виртуальную таблицу является вторым указателем.
- Указатель функции в виртуальной таблице является третьим указателем.
- Это 3 направления; подкладка невозможна.
C ++ стиль шаблона:
- Копирование объекта с функцией ().
- Нет виртуальной таблицы, так как тип этого объекта известен во время компиляции.
- Адрес функции известен во время компиляции.
- Это 0 косвенных указаний; возможна подкладка.
Шаблоны C ++ достаточно универсальны, чтобы использовать два других указанных выше стиля, а в случае встраивания они могут даже превосходить…
скомпилированные функциональные языки: (исключая JVM и Javascript в качестве целевых платформ из-за отсутствия "правильных вызовов хвоста")
- Указатель на функцию и ссылка на ее закрытие в регистрах машины.
- Обычно это не вызов функции, а GOTO-подобный прыжок.
- Для функций не требуется стек, нет адреса для возврата назад, нет параметров или локальных переменных в стеке.
- Функции имеют свои закрываемые закрытия, содержащие параметры, и указатель на следующую вызываемую функцию.
- Чтобы процессор мог предсказать скачок, адрес функции должен быть загружен в регистр как можно раньше.
- Это 1 косвенное направление с возможным прогнозом скачка; все почти так же быстро, как встроено.