Практика.pptx
- Количество слайдов: 21
Наследование Виртуальные методы
Виртуальный метод (виртуальная функция) — в объектно-ориентированном программировании метод (функция) класса, который может быть переопределён в классах-наследниках так, что конкретная реализация метода для вызова будет определяться во время исполнения.
Базовый класс Свойство А Синтаксис простого наследования class A { }; class B { }; class C: public A { }; class D: public B Определены в базовом, но { доступны в производном }; Определено в производном классе Свойство Б Свойство В Стрелка означает наследование Производный класс Свойство А Свойство Б Свойство В Свойство Г
ПРИМЕР Рассмотрим базу данных служащих некоторой компании. Сделаем три категории служащих: менеджер, ученые и рабочие.
Сделаем нашу программу применяя виртуальные функции. Для чего они нужны? Виртуальные функции позволяют решать прямо в процессе выполнения программы, какую именно функцию вызывать. Без их использования это решение принимается на этапе компиляции программы. В частности, они разрешают использование функций, вызванных из массива указателей на базовый класс, который на самом деле содержит указатели на множество порожденных классов
Они все работники одного предприятия, но у них могут быть свои особенности их работы
Работник Имя Номер Менеджер Ученый Должность Сборы клуба Публикации В базе данных хранятся имена служащих всех категорий и их идентификационные номера. Однако в информации о менеджерах содержится еще и Рабочий название их должности и их взносы в гольфклубы, а в информации об ученых-количество опубликованных статей.
Создаем класс работник Класс employee это наш работник. В свою очередь работника предприятия могут быть менеджеры, ученые и обычные рабочие. Для менеджеров создаем класс class manager, в нем будет храниться информация о менеджерах, точнее его должность и его взносы в гольф клубы. Для ученых создаем класс class scientist, в нем будет храниться информация об ученых, точнее сколько раз он опубликовывал свои работы. Для обычного рабочего создаем класс class laborer. В этом классе уточняющих данных нет
Описываем класс работник employee class employee // некий сотрудник { private: char name[ LEN ]; // имя сотрудника unsigned long number; // номер сотрудника public: void getname() { cout << " Vvedite familiyu: "; cin >> name; cout << " Vvedite nomer: "; cin >> number; } void putname ( ) { cout << "n Familiya: " << name; cout << "n Nomer: " << number; } virtual void getdata() {cout << " Ne virtualniy metod: "; } virtual void putdata() {cout << " Ne virtualniy metod: "; } };
В нашем классе class employee описаны два обычных и два виртуальных метода void getname() этот метод объявляется для ввода информации о работниках, то есть их фамилии и идентификационные номера. void putname ( ) этот метод выводить на экран информацию virtual void getdata() и virtual void putdata() это два виртуальных метода. Первый метод getdata() запрашивает у пользователя должность и взносы в гольф клуб, если он запускается для обслуживания класса manager, или число публикаций для scientist. А метод putdata() выводит данные на экран.
Описываем класс manager class manager : public employee // менеджер { private: char title[ LEN ]; // должность, например вице-президент double dues; // сумма взносов в гольф-клуб public: void getdata( ) { employee: : getname ( ); cout << " Vvedite dolzhnost: "; cin >> title; cout << " Vvedite summu vznosov v golf-klub: "; cin >> dues; } void putdata( ) { employee: : putname ( ); cout << "n Dolzhnost: " << title; cout << "n Summa vznosov v golf-klub: " << dues; cout << "n"; } };
В классе manager описаны функции getdata() и putdata( ). Эти функции в базовом классе описаны как виртуальные. getdata() запрашивает должность и взносы в гольф клуб. putdata( ) выводит полную информацию на экран. Также в них вызываются обычные методы базового класса employee: : getname ( ); и employee: : putname ( );
Описываем класс scientist class scientist : public employee // ученый { private: int pubs; // количество публикаций public: void getdata ( ) { employee: : getname ( ); cout << " Vvedite kolichestvo publikaciy: "; cin >> pubs; } void putdata ( ) { employee: : putname ( ); cout << "n Kolichestvo publikaciy: " << pubs; cout << "n"; } };
В классе scientist описаны функции getdata() и putdata( ). Эти функции в базовом классе описаны как виртуальные. getdata() запрашивает количество публикаций. putdata( ) выводит полную информацию на экран. Также в них вызываются обычные методы базового класса employee: : getname ( ); и employee: : putname ( );
Описываем класс laborer class laborer: public employee // рабочий { public: void getdata( ) { employee: : getname ( ); } void putdata( ) { employee: : putname ( ); cout << "n"; } };
В классе laborer описаны функции getdata() и putdata( ). Эти функции в базовом классе описаны как виртуальные. В них только вызываются обычные методы базового класса employee: : getname ( ); и employee: : putname ( ); которые запрашивают информацию и выводят ее на экран.
В главной программе создаем массив указателей на базовый класс employee* emp. PTR[LEN]; emp. PTR[n] = new manager; // заносим нового работника то есть //менеджера emp. PTR[n++]->getdata(); // сразу после того как мы заносим нового //работника , мы запрашиваем данные о нем, здесь происходит позднее связывание или динамическое //связывание, то есть компилятор откладывает принятие решения до запуска программы, а когда уже //известно на что указывает emp. PTR[LEN] тогда будет запущена соответствующая версия getdata(); for(j=0; j
Главная программа int main ( ) { employee* emp. PTR[LEN]; int n=0; int j; emp. PTR[n] = new manager; emp. PTR[n++]->getdata(); emp. PTR[n] = new scientist; emp. PTR[n++]->getdata(); emp. PTR[n] = new laborer; emp. PTR[n++]->getdata(); for(j=0; j
Результат работы
Если же в базовом классе мы функции virtual void getdata() и virtual void putdata() не опишем как виртуальные то будут вызываться эти же функции только базового класса, то есть функции производного класса void getdata() и void putdata() не будут участвовать в программе. И результат будет таков:
Итак, мы увидели что можно вызывать функции с помощью одного и того же выражения, то есть могут выполнятся абсолютно разные функции при одном и том же вызове! В нашем случае если указатель указывает на менеджера то запрашиваются данные менеджера. Функции выглядит одинаково это выражение getdata(); , но реально вызываются разные функции, в зависимости от значения emp. PTR[LEN].