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

  Юрий Ворон  | 

    | 

  Обновлено 18 Окт 2018  | 

 443

Как мы уже знаем из предыдущих уроков, выполнение программы в 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 (4 оценок, среднее: 5,00 из 5)
Загрузка...

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

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

ВОЛШЕБНАЯ ТАБЛЕТКА ПО С++