Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Полиморфизм. Виртуальные функции..doc
Скачиваний:
9
Добавлен:
15.07.2019
Размер:
62.98 Кб
Скачать

Тема 2.4 Полиморфизм. Виртуальные функции.

Полиморфи́зм (в языках программирования) — возможность объектов с одинаковой спецификацией иметь различную реализацию.

В объектно-ориентированных языках класс является абстрактным типом данных. Полиморфизм реализуется с помощью наследования классов и виртуальных функций. Класс-потомок наследует сигнатуры методов класса-родителя, а реализация, в результате переопределения метода, этих методов может быть другой, соответствующей специфике класса-потомка. Другие функции могут работать с объектом класса-родителя, но при этом вместо него во время исполнения будет подставляться один из классов-потомков. Это называется поздним связыванием.

Основные концепции:

  1. Полиморфизм представляет собой способность объекта изменять форму во время выполнения программы.

  2. Для создания полиморфных объектов программа должна использовать виртуальные (virtual) функции.

  3. Виртуальная (virtual) функция — это функция базового класса, перед именем которой стоит ключевое слово virtual.

  4. Любой производный от базового класс может использовать или перегружать виртуальные функции.

  5. Для создания полиморфного объекта следует использовать указатель на объект базового класса.

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

#include <stdio.h>

#include <iostream.h>

#include <conio.h>

class phone {

public:

void dial(char *number) {cout<<"Connecting..."<<endl;}//метод соединение

phone(char *number) { strcpy(phone::number, number); }

protected:

char number[13];

};

//Создание объекта-телефона класса phone:

Void main(void) {

phone telephone("555-1212");

telephone.dial("212-555-1212");

getch();

}

Программа не делает различий между дисковым и кнопочным телефонами, также она не поддерживает платные телефоны (пользователь должен заплатить 250 руб, чтобы позвонить).

Поскольку нам известно наследование, то необходимо создать классы touch_tone(кнопочный) и pay_phone(платный) из класса phone, как показано ниже:

class touch_tone : public phone {

public:

void dial(char *number){ cout<<"Connecting by touch_tone..."<<endl;}

touch_tone(char *number) : phone(number){ }

};

class pay_phone: public phone {

public:

Void dial(char *number) {

cout<<"Pay "<< amount <<" r"<<endl<<"Connecting... "<< number <<endl;}

pay_phone(char *number, int amount) : phone(number) {

pay_phone::amount = amount;

}

private:

Int amount;

};

Как видно, классы touch_tone и pay__phone определяют свой собственный метод dial. Следующая программа использует эти классы для создания объектов rotary, touch_tone и pay_phone:

void main (void) {

phone rotary("303-555-1212");

rotary.dial("602-555-1212");

touch_tone telephone("555-1212");

telephone.dial("212-555-1212");

pay_phone city_phone("555-1111", 250);

city_phone.dial("212-555-1212");

}

Если вы откомпилируете и запустите эту программу, на экране дисплея появится следующий вывод:

Connecting...

Connecting by touch_tone...

Pay 250 r

Connecting... 212-555-1212

Как уже упоминалось, полиморфный объект представляет собой такой объект, который изменяет форму во время выполнения программы. Предыдущая программа, например, не использовала полиморфные объекты. Иначе говоря, в ней нет объектов, которые бы изменяли форму.

СОЗДАНИЕ ПОЛИМОРФНОГО ОБЪЕКТА-ТЕЛЕФОНА

Для того, чтобы ваш объект-телефон мог эмулировать дисковый, кнопочный или платный телефон на выбор необходимо использовать полиморфный объект. Другими словами, для одного звонка объект-телефон мог бы представлять кнопочный аппарат, для другого выступал бы как платный телефон и т.д. Иначе говоря, от одного звонка к другому ваш объект-телефон должен изменять форму.

В этих разных классах телефона существует единственная отличающаяся функция — это метод dial. Для создания полиморфного объекта вы сначала определяете функции базового класса, которые отличаются от функций производных классов тем, что они виртуальные, предваряя их прототипы ключевым словом virtual, как показано ниже:

class phone {

public:

virtual void dial(char *number) {cout<<”Connecting...”<<endl;}

phone(char *number) { strcpy(phone::number, number); };

protected:

char number[13] ;

};

Далее в программе создается указатель на объект базового класса. Для вашей телефонной программы вы создадите указатель на базовый класс phone:

phone *poly_phone;

touch_tone telephone("555-1212");

Для изменения формы объекта вы просто присваиваете этому указателю адрес объекта производного класса, как показано ниже:

poly_phone = (phone *) &telephone;

Символы (phone *), которые следуют за оператором присваивания, являются оператором приведения типов, который сообщает компилятору C++, что все в порядке, необходимо присвоить адрес переменной одного типа (touch_tone) указателю на переменную другого типа (phone). Поскольку ваша программа может присваивать указателю объекта poly_phone адреса различных объектов, то этот объект может изменять форму, а следовательно, является полиморфным. Следующая программа использует этот метод для создания объекта-телефона. После запуска программы объект poly_phone меняет форму с дискового телефона на кнопочный, а затем на платный:

#include <stdio.h>

#include <iostream.h>

#include <conio.h>

#pragma argsused

class phone {

public:

virtual void dial(char *number) {cout<<"Connecting..."<<endl;}

phone(char *number) { strcpy(phone::number, number); };

protected:

char number[13] ;

};

class touch_tone : phone {

public:

void dial(char * number){ cout<<"Connecting by touch_tone..."<<endl;}

touch_tone(char *number) : phone(number){ }

};

class pay_phone: phone {

public: