русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Статическое или раннее связывание (static/early binding)


Дата добавления: 2015-07-09; просмотров: 648; Нарушение авторских прав


Давайте разберёмся, как происходит вызов обычных функций и методов классов. Вызов обычных функций и методов происходит через механизм, называемый статическим (статичным) связыванием (static binding) или ранним связыванием (early binding).

Раннее связывание использовалось во всех функциях и методах наших программ за исключением тех случаев, где мы использовали указатели на функции.

Когда мы запускаем сборку (building) программы, компилятор просматривает исходный код и превращает все операторы в команды процессора. Допустим, в коде встречается вызов какой-нибудь функции:

someFunction(arg); // some - какой-то

Если это обычная функция (не указатель на функцию), то при вызове используется механизм раннего связывания.

Во время компиляции для кода (определения) функции выделяется память, и назначаются адреса для каждого оператора. Первый адрес в определении (теле функции) является адресом функции. При вызове someFunction, процессор будет переходить на адрес функции и начнёт выполнять тело функции. Самое важное здесь то, что адрес функции назначается во время компиляции, и именно этот адрес используется при вызове функции. Это и есть раннее или статичное связывание. Т.е. имя функции крепко привязано к адресу функции.

Теперь взглянем на небольшой пример:

class Base

{ public: void Method () { cout << "Базовый класс\n"; } };

class Derived : public Base

{};

// внутри main

Base b; Derived d; b.Method(); d.Method();

//-------- Вывод:

Базовый класс Базовый класс

На экран будет выведено две строки Базовый класс. На этапе компиляции память выделяется для двух копий Method - для базового класса и для производного. Оба адреса привязываются к именам методов: Base::Method, Derived::Method. Т.е. когда в коде мы вызываем Method, то вызывается метод, соответствующий типу объекта. Чтобы увидеть, что для каждого объекта вызывается свой метод, давайте переопределим метод Derived::Method:



public:

void Method () { cout << "Производный класс\n"; }

 

//-------- Вывод:

Базовый класс Производный класс

Здесь хорошо видно, что вызываются два разных метода. Теперь следующий пример. Определения классов оставим без изменений. Поработаем с указателями:

Замечание

В данном примере пока что не будем обращать внимание, зачем нужно в указатель на Base помещать объект Derived.

Base* b = new Derived; Derived* d = new Derived;

b->Method(); d->Method();

//-------- Вывод:

Базовый класс Производный класс

Самое важное здесь то, что компилятор спокойно "проглатывает" тот факт, что указатель на Base указывает на производный класс. Дело в том, что базовый и производный классы являются совместимыми по типу.

Во время выполнения программы процессор видит, что b - это указатель на Base. Процессор не обращает внимание, что на самом деле этот указатель указывает на объект Derived. При вызове метода объекта b процессор переходит к адресу Base::Method.

Чтобы объект b вызвал метод Derived::Method, нужно привести тип. Например, так:

static_cast<Derived*>(b)->Method();

//-------- Вывод:

Производный класс

Это примеры раннего связывания (статического). Обратите внимание, что в этом примере мы помещали в указатель на Base объект Derived, а не наоборот:

Derived* d = new Base; b->Method(); d->Method();

Этот случай нам не интересен. К тому же при компиляции возникнет ошибка - здесь нужно использовать static_cast или dynamic_cast. Практическое применение имеет только случай, когда Base* указывает на Derived. В этом случае появляется возможность использовать полиморфизм (polymorphism).



<== предыдущая лекция | следующая лекция ==>
Последовательность выполнения работы | Полиморфизм (polymorphism) и полиморфные типы (polymorphic types)


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.057 сек.