Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOP_LAB_Part_2_Obyektno-orientov_progr.DOC
Скачиваний:
11
Добавлен:
03.05.2019
Размер:
418.3 Кб
Скачать

Ієрархія об'єктів

Ієрархія класів є ієрархія за принципом успадкування, тобто типу "це є різновид того". Наприклад, "робітник є різновид персони", “автомобіль” є різновид “транспортного засобу”. На відміну від цього ієрархія об'єктів — це ієрархія за принципом входження, тобто типу "це є частиною того". Наприклад, "установа - частина заводу", “двигун” частина “автомобіля”. Таким чином об'єкти нижнього рівня ієрархії включаються в об'єкти більш високого рівня, що є для них групою.

Ітератор.

Ітератори дозволяють виконувати деякі дії для кожного елемента визначеного набору даних.

For all елементів набору { дії}

Такий цикл міг би бути виконаний для всього набору, наприклад, щоб надрукувати всі елементи набору. Чи міг би шукати деякий елемент, що задовольняє визначеній умові, і в цьому випадку такий цикл може закінчитися, як тільки буде знайдений необхідний елемент.

Ми будемо розглядати ітератори як спеціальні методи класу-групи, що дозволяють виконувати деякі дії для всіх об'єктів, включених у групу. Прикладом ітератора є метод Show.

Нам би хотілося мати такий ітератор, що дозволяв би виконувати над всіма елементами групи дії, задані не одним з методів об'єкта, а довільною функцією користувача. Такий ітератор можна реалізувати, якщо цю функцію передавати йому через покажчик на функцію.

Визначимо тип покажчика на функцію в такий спосіб:

typedef void(*PF)(TObject*,< додаткові параметри>);

Функція має обов'язковий параметр типу TObject чи TObject*, через який їй передається об'єкт, для якого необхідно виконати визначені дії.

Метод - ітератор з'являється в такий спосіб:

void TGroup::ForEach(PF action,< додаткові параметри >);

де

action-єдиний обов'язковий параметр-покажчик на функцію, що викликається для кожного елемента групи;

додаткові параметри – параметри, що передаються функції, яка викликається.

Потім визначається покажчик на функцію і ініціюється переданою ітератору функцією.

PF pf=myfunc;

Тоді ітератор буде викликатися, наприклад для додаткового параметра типу int, так:

gr.ForEach(pf,25);

Тут gr-об'єкт-група.

Динамічна ідентифікація типів.

Динамічна ідентифікація типу характерна для мов, у яких підтримується поліморфізм. У цих мовах можливі ситуації, у яких тип об'єкта на етапі компіляції невідомий.

У С++ поліморфізм підтримується через ієрархії класів, віртуальні функції і покажчики базових класів. При цьому покажчик базового класу може використовуватися або для вказівки на об'єкт базового класу, або для вказівки на об'єкт будь-якого класу похідного від цього базового.

Нехай група містить об'єкти різних класів і необхідно виконати деякі дії тільки для об'єктів визначеного класу. Тоді в ітераторі ми повинні розпізнавати тип чергового об'єкта.

У стандарт мови С++ включені засоби RTTI (Run-Time Type Idendification)- динамічна ідентифікація типів. Ці засоби реалізовані в останніх системах Borland C++ (версій 4.0 і вище).

Інформацію про тип об'єкта одержують за допомогою оператора typeid, визначення якого містить заголовний файл <typeinfo.h>.

Є дві форми оператора typeid:

typeid (об'єкт)

typeid (ім'я_типу)

Оператор typeid повертає посилання на об'єкт типу type_info.

У класі type_info перевантажені операції == і != забезпечують порівняння типів.

Функція name() повертає покажчик на ім'я типу.

Є одне обмеження. Оператор typeid працює коректно тільки з об'єктами, у яких визначені віртуальні функції. Більшість об'єктів мають віртуальні функції, хоча б тому, що звичайно деструктор є віртуальним для усунення потенційних проблем з похідними класами. Коли оператор typeid застосовують до неполіморфного класу (у класі немає віртуальної функції), які одержують покажчик чи посилання базового типу.

Приклади.

1.

#include<iostream.h>

#include<typeinfo.h>

class Base{

virtual void f(){};

//…

};

class Derived: public Base{

//…

};

void main()

{int i;

Base ob,*p;

Derived ob1;

cout<<typeid(i).name(); //Виводиться int

p=&ob1;

cout<<typeid(*p).name(); // Виводиться Derived

}

2.

//початок див. вище

void WhatType(Base& ob)

{cout<< typeid(ob).name()<<endl;

}

void main()

{

Base ob;

Derived ob1;

WhatType(ob); //Виводиться Base

WhatType(ob1); //Виводиться Derived

}

3.

//початок див. вище

void main()

{

Base *p;

Derived ob;

p=&ob;

if(typeid(*p)==typeid(Derived)) cout<<“p указує на об'єкт типу Derived”;

}

Якщо при звертанні typeid(*p), p=NULL, то збуджується виняткова ситуація bad_typeid

Порядок виконання роботи.

  1. Доповнити ієрархію класів лабораторної роботи №2 класами “група”.

Наприклад, для предметної області ФАКУЛЬТЕТ можна запропонувати класи “факультет”, “студентська група”, “кафедра”. Рекомендується створити абстрактний клас - “підрозділ”, що буде предком усіх груп і абстрактний клас TObject, що знаходиться на чолі всієї ієрархії.

2.Написати для класу-групи метод - ітератор.

3.Написати процедуру функції, що виконується для всіх об'єктів, що входять у групу (дивися приклади в додатку).

4.Написати демонстраційну програму, у якій створюються, показуються і руйнуються об'єкти-групи, а також демонструється використання ітератора.

Методичні вказівки.

1.Клас-група повинен відповідати ієрархії класів лабораторної роботи №2, тобто об'єкти цих класів повинні входити в групу. Наприклад, для варіанта 1 може бути запропонована наступна ієрархія клас

TObject(абстр. клас)

Персона(абстр. клас) Підрозділ (абстрактна група)

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]