Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка_new_ООП.doc
Скачиваний:
3
Добавлен:
09.11.2019
Размер:
133.63 Кб
Скачать

Лабораторная работа №2 наследование

Цель работы: Получить практические навыки …

    1. Теоретические сведения Виртуальные функции

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

Функция-член класса объявляется как виртуальная указанием ключевого слова virtual. Методы в производных классах, заменяющие виртуальную функцию базового класса должны объявляться с тем же именем, тем же списком параметров и типом возвращаемого значения, что и соответствующая функция базового класса. Если из производного класса не образуется новых производных классов, ключевое слово virtual в описании функции можно опустить.

Если в производном классе нет объявления функции с тем же именем, что и виртуальная функция базового класса, будет вызываться функция базового класса.

class CObject
{
protected:
float x,y;
public:
CObject() {x=0; y=0;};
CObject(float x,float y){this->x=x; this->y=y;}
~CObject() {};
virtual void draw() = 0;
 
};
Рисунок 14 –Пример виртуальной функции

Такая функция называется “чистой” (pure) виртуальной функцией, а объектный тип, содержащий ее объявление, называется абстрактным объектным типом. В программе не могут создаваться экземпляры абстрактных типов, такой тип может использоваться только для образования производных типов, причем в производном типе следует либо снова определить эту виртуальную функцию как чистую, либо объявить ее как обычную виртуальную функцию, выполняющую конкретные действия. Виртуальные функции особенно полезны, когда к методом класса требуется обращаться через указатель на экземпляр класса, а сам этот указатель имеет тип указателя на базовый класс.

В примере ниже как раз проиллюстрирован подобный случай. Класс CWorld содержит массив указателей на объекты класса CIObject. При работе с ними вызываются виртуальный метод класса CIObject draw(), который должен отрисовывать текущий объект на экране. Метод этот вызывается через указатель на класс CIObject. Однако, эти указатели на самом деле могут указывать на классы-потомки CIObject, такие, как CCircle, в которых метод draw() переопределён для рисования уникальной формы.

class CCircle: public CIObject
{
  public:
    CCircle() {x=0;y=0;};
   ~CCircle() {};  
   virtual void draw(); // переопределена
}

void CCircle::draw()
{
  setcolor(14);
  circle(x,y,10); 
}
Рисунок 15 - Переопределение виртуальной функции draw()

void CWorld::render()
{
  for (int i=0;i<objectsn; i++)
   objects[i]->draw();

  player.draw();
  
}
Рисунок 16 - Вызов draw() через указатель базового класса