Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Полиморфизм, раннее и позднее связывание, виртуальные функции
«В С++ одним из наиболее туманных понятий, с точки зрения новичков, является полиморфизм. Само слово полиморфизм достаточно экзотично и, видимо, по этой причине оно прижилось, хотя есть и другие, может быть, более подходящие термины. Программисты – странный народ. Они часто стремятся сделать из мухи слона просто так, ради прикола. Существуют даже ежегодные состязания среди программистов по С, где первый приз получает тот, кто напишет самую труднопонимаемую программу. Программисты черпают информацию из книг, статей в журналах, материалов конференций и т.п. Чем больше людей интересуются языком, тем лучше. Странно звучащие термины скорее вызовут любопытство слушателя или читателя, чем обыденная речь. А любопытство, в свою очередь, стимулирует изучать новые свойства языка. Чем больше людей изучают язык, тем он популярнее. Именно так и случилось с С++ и термин полиморфизм привлек внимание не одного любопытного читателя» Тэд Фейсон. Полиморфизм –от греческих словpoly (много), morphos (форм) – множественность форм. Практически с понятием полиморфизма мы уже сталкивались – это перегрузка функций и операций. При наследовании оно тоже используется через понятие виртуальных функций.
Раннее (статическое) и позднее (динамическое) связывание
Вспомним пример классов A и B из п.1.
class A { private: int d1, d2, d3; public: A() {d1 = d2 = d3 = 0;} // конструктор по умолчанию A(int x, int y, int z) {d1 = x; d2 = y; d3 = z;} // конструктор с аргументами void PrintA() {cout << d1 << ’ ‘ << d2 << ’ ‘ << d3;} };
Определим новый класс B
class B: public A[,private A1,...] // класс B порожден из класса A { int d3, d4; public: B(); // конструктор без аргументов B(int, int, int); // конструктор с аргументами int Sum3(); void PrintB(); };
Рассмотрим вариант, когда функции вывода член-данных в этих классах имеют одинаковое имя Print():
void A:: Print() {cout << d1 << ’ ‘ << d2 << ’ ‘ << d3 << ’ ‘;} void B:: Print() {A:: Print(); cout << d3 << d4;}
Функции Print() нарушают условия перегрузки для обычных функций: у них не только одинаковое имя, но и список аргументов. Однако это не приведет к сообщению об ошибке компилятором, так как, например, в таком фрагменте:
A x; B y; x.Print(); // Print() класса A y.Print(); // Print() класса B
выбор функции компилятор определяет по типу объектов: x или y. Причем этот выбор осуществляется еще на этапе компиляции. Такое связывание вызова функции с конкретной функцией на этапе компиляции и называется ранним или статическим связыванием. Используя свойство преобразования объектов, ссылок и указателей порожденных классов к базовому, программы можно делать более гибкими. Например, в некотором месте программы может вызываться функция Print() из любого класса, причем компилятор на этапе трансляции не может определить адрес вызываемой функции, но он может задать алгоритм вычисления этого адреса при выполнении программы. Например, пусть еще определен класс C:
class C: public A {int d5; public: C() {d5 = 100;} C(int a, int b, int c, int d): A(a, b, c), d5(d) { } void Print() {A:: Print(); cout << ’ ‘ << d5;} ... };
и программа:
void main() {A x; B y(1, 2, 3, 4, 5, 6); C z; A * pa; int k; cin >> k; switch (k) {case 0: pa = &x; break; case 1: pa = &y; break; case 2: pa = &z; break; default:: cout <<»СТОП!»; return; } pa –> Print(); ... }
В этом примере до исполнения программы неизвестно, адрес какого объекта будет занесен в указатель pa и, следовательно, функция Print() из какого класса – A, B или C будет вызвана. Другими словами, связать вызов функции Print() с конкретным экземпляром этой функции возможно только при выполнении программы по специальному алгоритму (см. п.5.5). Это так называемое позднее или динамическое связывание. Но в приведенном выше примере будет пока вызываться функция A::Print() и выводить базовую часть любого объекта. Чтобы происходил действительно вызов разных функций в зависимости от значения указателя pa, надо функцию Print() объявить виртуальной.
|
|||||
Последнее изменение этой страницы: 2021-12-07; просмотров: 133; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.221.63.134 (0.008 с.) |