Московский государственный технический университет
им. Н. Э.
Баумана
Утверждаю:
___________________
«___»__________2005 г.
___________________
по курсу ПППО
«Наследование, виртуальные функции и абстрактные классы»
10
(количество листов)
ИСПОЛНИТЕЛЬ:
студент группы ИУ5-63
Тесленко М.В.
______________
«___»__________2005 г.
МОСКВА 2005
1. Цель работы.
Целью
лабораторной работы является дополнительное изучение оболочки (IDE) системы
программирования BC 3.1 C++ , способов наследования классов, использование
виртуальных функций, понятий абстрактного класса и виртуального вызова функций.
Студенты создают свои классы и исследуют механизмы вызова виртуальных функций.
Учатся проектировать собственные классы и отображать результаты на диаграммах
классов и объектов.
2. Порядок работы.
В процесса лабораторной
работы( она рассчитана на 4 часа) необходимо изучить и выполнить:
1. Порядок и особенности работы с оболочкой:
использование отладчика и средств просмотра классов;
2. Выполнить описание четырех собственных классов (Absrt,
Deriv1 ,Deriv2 и Deriv3 названия классов нельзя изменять), связанных следующим
образом: Absrt - абстрактный класс, наследованный от Object ( из classlib);
Deriv1 - наследуется от Absrt, Deriv2 наследуется от Deriv1, Deriv3 наследуется
от Deriv1.
3. Классы Deriv1 ,Deriv2 и Deriv3, не являются
абстрактными и имеют, по крайней мере, одну виртуальную функцию, определенную в
классе Absrt как чистая виртуальная функция (тело такой функции обозначается
так - "=0").
4. Построить диаграмму наследования классов для ЛР.
5. Описать объекты классов Absrt, Deriv1 ,Deriv2 и
Deriv3(названия фиксированы - a1, d1, d2, d3) и выполнить их инициализацию и
инициализацию указателей на эти типы, которые описываются отдельно( pa1, pd1,
pd2, pd3);
6. Построить диаграмму объектов для лабораторной работы.
7. Выполнить вызовы виртуальных функций всех классов и
объектов через имена объектов и указатели,
в том числе через указатель на
базовый абстрактный класс( pa1) – это виртуальный вызов!!!.
8. Занести объекты разных типов в один список типа LIST (из classlib см. ЛР 3).
9. Распечатать списка с помощью цикла, функции printOn и собственной виртуальной
функции print , на основе
класса LISTITERATOR.
3. Перечень ошибок.
При
разработке и отладке программы были обнаружены и исправлены различные
синтаксические ошибки.
4. Диаграмма классов.
Object – абстрактный базовый класс
для всех объектов
Функции:
isA – возвращает
ID класса
isEqual –
определяет равен ли объект другому
printOn – отображает
объект
Abstr, Deriv1, Deriv2, Deriv3 - четыре
собственных класса (Absrt, Deriv1 ,Deriv2 и Deriv3 названия классов нельзя
изменять), связанные следующим образом: Absrt - абстрактный класс,
наследованный от Object ( из classlib); Deriv1 - наследуется от Absrt, Deriv2
наследуется от Deriv1, Deriv3 наследуется от Deriv1.
Container – абстрактный класс
родитель всех классов, включает все классы способные содержать 0 или более
элементов
Collection – абстрактный класс
“коллекционных” структур
List – класс списка
Функции:
add – добавляет
элемент
detach – удаляет
объект
initIterator-
создаёт итератор
flush – удаление
всех объектов из списка
ListIterator – итератор списка
Функции
current –
возвращает ссылку на текущий объект
++ - увеличивает значение итератора на 1
restart –
перемещает итератор в первую непустую точку списка
5. Диаграмма объектов.
6. Листинг программы.
Lab_4_1.cpp
/* abstr.cpp - main
program for lab#4
* Teslenko,
IU5-63, var#18
*/
#include <conio.h>
#include <list.h>
#include "abstr.h"
int main ()
{
clrscr ();
print_info();
Deriv1 d4 ("Deriv4
for test =");
Deriv1 d1 ("abstr -> deriv1"); //инициализация объектов классов d1, d2, d3
Deriv2 d2 ("deriv1 ->
deriv2");
Deriv3 d3 ("deriv1 ->
deriv3");
//объявление указателей на объекты классов d1, d2, d3
Deriv1* pd1 = &d1;
Deriv2* pd2 = &d2;
Deriv3* pd3 = &d3;
Deriv1* pd4 = &d4;
Abstr* pa; //абстрактный указатель
List ListDerive; //объявление списка
cout << "Object.print() :" << endl; //вывод по имени объекта
d1.print(cout);
d2.print(cout);
d3.print(cout);
d4.print(cout);
d4
= "After Change";
//вывод через указатель
cout << endl << "Pointer->print()
:" << endl;
pd1->print(cout);
pd2->print(cout);
pd3->print(cout);
pd4->print(cout);
//вывод через абстрактный указатель
cout << endl <<
"Abstract_pointer->print() :" << endl;
pa = pd1;
pa->print(cout);
pa = pd2;
pa->print(cout);
pa = pd3;
pa->print(cout);
getch ();
//заполнение листа 15-ю объектами классов d1, d2, d3
cout << endl << endl
<< "Filling of 15 strings"
<< endl;
char
a[5]="dList";
char *strM;
char *strT;
strM=(char
*)calloc(8,sizeof(char));
strM=a;
for(int i=0;i<5;i++)
{*(strM+5)='1'; *(strM+6)=48+i; *(strM+7)='\0'; ListDerive.add(*new
Deriv1(strM));};
for(i=0;i<5;i++)
{*(strM+5)='2'; *(strM+6)=48+i; *(strM+7)='\0'; ListDerive.add(*new
Deriv2(strM));}
for(i=0;i<5;i++)
{*(strM+5)='3'; *(strM+6)=48+i; *(strM+7)='\0'; ListDerive.add(*new
Deriv3(strM));}
//вывод списка при помощи PrintOn
cout << "Printing list
with printOn():" << endl;
printOnList (ListDerive);
getch();
//
with print()
cout << "Printing list
with print():" << endl;
printList (ListDerive);
getch ();
//удаление всех объектов класса Deriv1 and Deriv3 из листа
cout << endl <<
"Deleting Deriv1 and Deriv3 objects from list:" << endl;
ListIterator it (ListDerive);
it.restart();
while ((int)it)
{
pa = (Abstr*)
&it.current();
it++;
if (pa -> need_del
())
{
cout
<< "Deleting object " << pa->get_cp() << endl;
ListDerive.detach
(*pa, TShouldDelete::Delete);
}
}
// вывод лста после удаления
cout << "List after
deleting:" << endl;
printList (ListDerive);
getch ();
return 0;
}
// вывод листа при помощи printOn()s
void printOnList (List& l)
{
ListIterator li (l);
cout << "List of my
objects: " << endl;
for_each (li)
{
cout << " ";
li.current().printOn(cout);
}
}
// вывод листа при помощи print()s
void printList (List& l)
{
ListIterator li (l);
cout << "List of my
objects: " << endl;
for_each (li)
{
cout << '\t';
((Abstr*)
&li.current())->print(cout);
}
}
Lab_4_2.cpp
#include <iostream.h>
void print_info()
{
cout << " Lab work 4 of PPPO";
cout << "\nTeslenko
Maxim IU5-63 Variant 18 \n" << endl;
}
Abstr.h
/* abstr.h - definitions
for lab#4
* Teslenko,
IU5-63, var#18
*/
/* abstr.h - definitions
for lab#4
* Teslenko,
IU5-63, var#18
*/
#include <iostream.h>
#include <object.h>
#include <string.h>
#define SIZE 20
#define DERIV1_ID 1
#define DERIV2_ID 2
#define DERIV3_ID 3
#define DERIV1_STRING "Deriv1"
#define DERIV2_STRING "Deriv2"
#define DERIV3_STRING "Deriv3"
#define DERIV1_HASH 1
#define DERIV2_HASH 2
#define DERIV3_HASH 3
#define NELEMS 5
#define for_each(iter) for (iter.restart(); (int) iter; iter++)
void get (istream& i, char* p, int n, char echar = '\n');
class Abstr : public
Object //создание
класса Аbstr на основе класса Object
{
private:
char cp[SIZE];
public:
Abstr (char* s)
{if
(strlen (s) <= SIZE) strcpy (cp, s);}
Abstr ()
{memset
(cp, 0, SIZE);}
~Abstr () {}
virtual void print
(ostream &) const = 0;
const char* get_cp
() const {return cp;}
// Abstr& operator =
(char *stroka){if (strlen (stroka) <=SIZE) strcpy(cp, stroka); return
*this;};
virtual classType
isA() const = 0;
virtual char _FAR
*nameOf() const = 0;
virtual
hashValueType hashValue() const = 0;
virtual int
isEqual(const Object _FAR & ) const = 0;
virtual void
printOn(ostream _FAR & ) const = 0;
virtual int
need_del () = 0;
};
class Deriv1 : public Abstr //класс Deriv1
{
public:
Deriv1 (char *s) :
Abstr(s) {}
Deriv1 () : Abstr
() {}
~Deriv1 () {}
virtual void print
(ostream &o) const
{o
<< "Deriv1: " << get_cp () << endl;}
virtual classType
isA() const {return
DERIV1_ID;}
virtual char _FAR
*nameOf() const {return
DERIV1_STRING;}
virtual
hashValueType hashValue() const {return
DERIV1_HASH;}
virtual int
isEqual( const Object _FAR & o) const
{return
(o.isA() == DERIV1_ID) ?
(!strcmp
(((Deriv1*)this)->get_cp(), ((Deriv1&)o).get_cp())) : 0;}
virtual void
printOn(ostream _FAR & o) const {print(o);}
virtual int
need_del () {return 1;}
};
class Deriv2 : public Deriv1 //класс Deriv2
{
public:
Deriv2 (char *s) :
Deriv1 (s) {}
Deriv2 () : Deriv1
() {}
void print (ostream
&o) const
{o
<< "Deriv2: " << get_cp () << endl;}
virtual classType
isA() const {return
DERIV2_ID;}
virtual char _FAR
*nameOf() const {return
DERIV2_STRING;}
virtual
hashValueType hashValue() const {return
DERIV2_HASH;}
virtual int
isEqual( const Object _FAR & o) const
{return
(o.isA() == DERIV2_ID) ?
(!strcmp
(((Deriv2*)this)->get_cp(), ((Deriv2&)o).get_cp())) : 0;}
void
printOn(ostream _FAR & o) const {print(o);}
int need_del () {
return 0; }
};
class Deriv3 : public Deriv1 //класс Deriv3
{
public:
Deriv3 (char *s) :
Deriv1 (s) {}
Deriv3 () : Deriv1
() {}
void print (ostream
&o) const
{o
<< "Deriv3: " << get_cp () << endl;}
virtual classType
isA() const {return
DERIV3_ID;}
virtual char _FAR
*nameOf() const {return
DERIV3_STRING;}
virtual
hashValueType hashValue() const {return
DERIV3_HASH;}
virtual int
isEqual( const Object _FAR & o) const
{return
(o.isA() == DERIV3_ID) ?
(!strcmp
(((Deriv3*)this)->get_cp(), ((Deriv3&)o).get_cp())) : 0;}
void
printOn(ostream _FAR & o) const {print(o);}
int need_del () { return 1; }
};
void printOnList (List& l); //прототипы используемых функций
void printList (List& l);
void get (istream& i, char* p, int n, char echar);
void print_info ();
7. Листинг результатов работы.