Россия и Беларусь начали и продолжают войну против целого народа Украины!

Урок №166. Раннее и Позднее Связывания

  Юрий  | 

  |

  Обновл. 15 Сен 2021  | 

 38837

Как мы уже знаем из предыдущих уроков, выполнение программы в языке C++ происходит последовательно, строка за строкой, начиная с функции main(). Когда компилятор встречает вызов функции, то точка выполнения переходит к началу кода вызываемой функции. Откуда компилятор знает, что это нужно сделать?

При компиляции программы компилятор конвертирует каждый стейтмент программы в одну или несколько строк машинного кода. Каждой строке машинного кода присваивается собственный уникальный адрес. Так же и с функциями: когда компилятор встречает функцию, она конвертируется в машинный код и получает свой адрес.

Связывание — это процесс, который используется для конвертации идентификаторов (таких как имена переменных или функций) в адреса. Хотя связывание используется как для переменных, так и для функций, на этом уроке мы сосредоточимся только на функциях.

Раннее связывание

Большинство вызовов функций, которые встречает компилятор, являются прямыми вызовами функций. Прямой вызов функции — это стейтмент, который напрямую вызывает функцию. Например:

Прямые вызовы функций выполняются с помощью раннего связывания. Раннее связывание (или «статическая привязка») означает, что компилятор (или линкер) может напрямую связать имя идентификатора (например, имя функции или переменной) с машинным адресом. Помните, что все функции имеют свой уникальный адрес. Поэтому, когда компилятор (или линкер) встречает вызов функции, он заменяет его инструкцией машинного кода, которая сообщает процессору перейти к адресу функции.

Рассмотрим простую программу-калькулятор, в которой используется раннее связывание:

Поскольку add(a, b), subtract(a, b) и multiply(a, b) являются прямыми вызовами функций, то компилятор будет использовать раннее связывание. Он заменит вызов add(a, b) инструкцией, которая сообщит процессору перейти к адресу add(). То же самое выполнится и для subtract(a, b), и для multiply(a, b).

Позднее связывание


В некоторых программах невозможно знать наперёд, какая функция будет вызываться первой. В таком случае используется позднее связывание (или «динамическая привязка»). В языке C++ для выполнения позднего связывания используются указатели на функции. Вкратце, указатель на функцию — это тип указателя, который указывает на функцию вместо переменной. Функция, на которую указывает указатель, может быть вызвана через указатель и оператор вызова функции. Например, вызовем функцию add():

Вызов функции через указатель на функцию также известен как непрямой (или «косвенный») вызов функции. Следующая программа-калькулятор идентична вышеприведенной программе, за исключением того, что вместо прямых вызовов функций используется указатель на функцию:

Здесь мы указываем pFcn указывать на функцию, которую выберет пользователь. Затем мы вызываем через указатель функцию, которую выбрал пользователь. Компилятор не может использовать раннее связывание для выполнения вызова функции pFcn(a, b), так как он не может наперёд определить, на какую функцию pFcn будет указывать!

Позднее связывание менее эффективное, так как присутствует «посредник» между процессором и функцией. С ранним связыванием процессор может перейти непосредственно к адресу функции. С поздним связыванием процессор должен прочитать адрес, хранящийся в указателе, и только затем перейти к этому адресу. Этот дополнительный шаг и замедляет весь процесс. Однако преимущество позднего связывания заключается в том, что оно более гибкое, нежели раннее связывание, так как не нужно решать, какую функцию следует вызывать до, собственно, запуска самой программы.

На следующем уроке мы рассмотрим, как позднее связывание используется для реализации виртуальных функций.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (188 оценок, среднее: 4,87 из 5)
Загрузка...

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *