Таблица данных произвольных типов в памяти

  • Вид работы:
    Курсовая работа (т)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    85,35 Кб
  • Опубликовано:
    2013-08-06
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

Таблица данных произвольных типов в памяти

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РФ

ФГБОУВПО

БРЯНСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ

Кафедра «Информатика и программное обеспечение»








КУРСОВАЯ РАБОТА

Таблица данных произвольных типов в памяти

Вариант № 27


Выполнил студент гр. 11-ПрИ,

Васин А.В.






Брянск 2012

Оглавление

Задание

1. Теоретические аспекты

2. Реализация

2.1 Абстрактный базовый класс

2.2 Классы наследники

2.3 Класс таблицы объектов произвольных типов

3. Пример работы программы

Заключение

ВВЕДЕНИЕ

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

ЗАДАНИЕ

Необходимо разработать интерфейс для объединения в структуру данных множества объектов различных классов - абстрактный базовый класс object, для которого предусмотреть виртуальные методы: загрузки объекта из текстовой строки, выгрузки объекта в текстовую строку в динамической памяти, добавление объекта в последовательный двоичный файл, чтения объекта из последовательного двоичного файла, возврата указателя на строку с именем класса, сравнения двух объектов, объединения двух объектов (сложения), создания динамической копии объекта. Сделать классы хранимых объектов производными от абстрактного базового класса TObject.

1.     
Теоретические аспекты


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

Полиморфизм - возможность объектов с одинаковой спецификацией иметь различную реализацию. В данном случае спецификацией будет являться класс TObject. В нём описаны чисто виртуальные функции, предоставляющие обобщенный интерфейс для частных классов. Частные классы, в свою очередь, предоставляют реализацию виртуальных функций для работы с ними.

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

2.     
Реализация


2.1    Абстрактный базовый класс


Для того чтобы производные классы гарантированно имели уникальную реализацию интерфейсных функций, опишем их в базовом классе как чисто виртуальными. Таким образом, базовый класс становится абстрактным. Этим мы заранее предотвращаем потенциальные ошибки при наследовании.

Итоговый базовый класс представлен в листинге 3.1.

#define CMP_ERROR -2

#define CMP_A_LESS_B -1

#define CMP_A_EQUAL_B 0

#define CMP_A_GREATER_B 1TObject

{:void LoadFromString(const char* str)=0;//загрузить данные из строки char* SaveToString() const=0;//создать строку и записать туда данные

virtual const char* ClassName() const=0;//получить имя класса в виде строки

virtual char Compare(TObject &b) const=0;//сравнить два объекта

virtual TObject* Clone() const=0;//создать динамическую копию объекта

/*объединить объекты (каждый производный класс интерпретирует эту операцию по-разному)*/

virtual void Unite(TObject&)=0; ~TObject()//виртуальный деструктор

{

};

//перегруженные операторы ввода/вывода из потока

friend std::istream& operator >> (std::istream&, TObject&);std::ostream& operator << (std::ostream&, TObject&);

//функции, для записи данных в двоичном формате в файл

virtual void SaveToFile(FILE *)=0;void LoadFromFile(FILE *)=0;

};

Листинг 3.1 Абстрактный базовый класс, описывающий интерфейсную часть для работы с объектами производных классов.

Необходимо отдельно прокомментировать функцию Compare. Она принимает ссылку на объект абстрактного класса. В производных классах эта функция должна удостовериться, что сравниваемые объекты имеют одинаковый тип. Если объекты разно типовые, то функция должна вернуть значение CMP_ERROR. Иначе, после сравнения возвращается CMP_A_LESS_B или CMP_A_EQUAL_B, или CMP_A GREATER_B.

Определение дружественных перегруженных операторов >> и << :

std::istream& operator >> (std::istream& stream, TObject& obj)

{

char buf[1024];//строка с данными

stream>>buf; //считываем строку из потока

//вызываем виртуальную функцию для объекта obj c аргументом - строка buf:

obj.LoadFromString(buf);stream;

}::ostream& operator << (std::ostream& stream, TObject& obj)

{

char* str=obj.SaveToString();//сохранить данные в текстовую строку

stream<<str;//вывести строку на экран[] str;//удалить строку из динамической памятиstream;

}

2.2    Классы наследники


В качестве класса наследника рассмотрим класс TInteger, являющийся «обёрткой» обычных целых чисел. В листинге 3.2 приведено описание интерфейса класса.

#include "TObject.h"TInteger:public TObject

{

int data;//данные

public:

TInteger();//пустой конструктор

TInteger(TInteger&);//конструктор копирования

~TInteger();//виртуальный деструктор

TInteger operator=(TInteger&);

//ниже объявление уже не чистых виртуальных функций, унаследованных от TObject

const char *ClassName() const;* Clone() const;Compare(TObject&) const;LoadFromString(const char*);* SaveToString() const;Unite(TObject&);SaveToFile(FILE *);LoadFromFile(FILE *);

Листинг 3.2 Интерфейс класса TInteger

Рассмотрим полиморфные определения виртуальных функций, унаследованных от класса TObject.

Константная функция, возвращающая имя класса в виде константной строки:

const char *TInteger::ClassName() const

{

return "TInteger";

}

Константная функция, создающая копию объекта в динамической области памяти:

TInteger* TInteger::Clone() const

{new TInteger(*(TInteger*)this);

}

Константная функция сравнения двух объектов:

char TInteger::Compare(TObject& b) const

{

if(strcmp(ClassName(),b.ClassName())!=0)//если имена классов не совпадают

return CMP_ERROR;//вернуть информацию об ошибке

if(data<((TInteger&)b).data)//если данные меньше данных другого объекта

return CMP_A_LESS_B;//вернуть информацию «А меньше, чем Б»

if(data==((TInteger&)b).data)//если равны CMP_A_EQUAL_B;//вернуть «А эквивалентно Б»

return CMP_A_GREATER_B;//во всех других случаях «А больше, чем Б»

}

Функция считывания информации из строки:

void TInteger::LoadFromString(const char *inStr)

{(inStr==NULL || strlen(inStr)==0);//остановить выполнение, если строка пуста или указатель - NULL

sscanf(inStr,"%d",&data);//считать целое число из строки

}

Константная функция сохранения данных в строку:

char* TInteger::SaveToString() const

{

//размерерность целого числа (32 разрядная система) не превышает 16 знаков:

char buf[16];

sprintf(buf,"%d",data);//записать данные в строку

//создать строку, скопировать туда данные из buf и вернуть указатель:

return strdup(buf);

}

Функция объединения двух однотипных объектов. Для целых чисел - это арифметическое сложение.

void TInteger:Unite(TObject &b)

{

if(strcmp(ClassName(),b.ClassName())!=0)//если имена классов не совпадают

return;//закончить выполнение

data+=((TInteger&)b).data;//сложение

}

Функции сохранения и записи в файл. Предполагается, что файл уже открыт из вне, и функции передаётся уже существующий дескриптор.

void TInteger::SaveToFile(FILE *f)

{(f==NULL);(&data,sizeof(data),1,f);//запись в бинарный файл f данных

}TInteger::LoadFromFile(FILE *f)

{(f==NULL);(&data,sizeof(data),1,f);//считать данные из файла

}

2.3    Класс таблицы объектов произвольных типов


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

Интерфейс коллекции представлен в листинге 3.3.

#include "TObject.h"TCollection

{ **ppObjects;//динамический массив указателей на объекты типа TObject

unsigned size;//размер массива:();//конструктор(TCollection&);//конструктор копии

~TCollection();//деструктор unsigned Size();//возвращает размер таблицыAdd(TObject *pObj);//добавляет указатель на объект в конец таблицыFind(TObject* pObj);//ищет в таблице указатель pObj и возвращает индекс

TObject* Remove(unsigned i);//удаление по индексу

TObject* Remove(TObject*);//удаление по указателю

TObject* Access(unsigned i);//доступ к объекту по индексуDelete(unsigned i);//удаление объекта по индексуClear();//очистка все коллекции

void Save(const char *fileName);//сохранить коллекцию в файл fileNameLoad(const char *fileName);//загрузить коллекцию из файла

//перегруженные дружественные операторыstd::istream& operator >> (std::istream&, TCollection&);std::ostream& operator << (std::ostream&, TCollection&);

};

Листинг 3.3 Интерфейс для работы с коллекцией объектов разного типа

Рассмотрим наиболее важные с точки зрения концепции полиморфизма методы этой коллекции. Все остальные функции выполняют простую работу с указателями и памятью.

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

void TCollection::Save(const char *fileName)

{

FILE *f=fopen(fileName,"wb");//открыть файл в двоичном режиме для записи

if(f==NULL);(unsigned i=0;i<size;i++)//рассмотрим каждый объект в таблице

{

//указатель на строку с именем класса:

const char *className=ppObjects[i]->ClassName();char len=strlen(className);//длина строки с именем класса(&len,sizeof(len),1,f);//записать длину строки в файл

}(f);//закрыть файл

}

Листинг 3.4 Функция сохранения коллекции в файл.

Функция загрузки коллекции из файла представлена в листинге 3.5. Этой функции необходимо знать названия классов для создания конкретных объектов.

void TCollection::Load(const char *fileName)

{*f=fopen(fileName,"rb");(f==NULL);();//очистить коллекцию(1)

{

char len;//размер строки с именем класса

char className[256];//строка с именем класса

fread(&len,sizeof(len),1,f);//считать размер строки

if(feof(f))//если файл закончился

break;//остановить цикл

fread(className,sizeof(className[0]),len,f);//считать имя класса

className[len]='\0';

TObject *p=NULL;//указатель на объект произвольного типа

if(strcmp(className,"TInteger")==0)//если в файле было TInteger=new TInteger;//создать экземпляр класса TInteger

//иначе если в файле было TNumber

else if(strcmp(className,"TNumber")==0)=new TNumber;//то создать объект типа TNumber

if(p!=NULL)//если объект удалось создать

{

p->LoadFromFile(f);//считать его данные из файла

Add(p);//и добавить в коллекцию

}

//иначе, если объект не был создан, то дальнейшая корректная работа не возможна, //необходимо остановить выполнение функции:

else;

}(f);

}

Листинг 3.5 Функция загрузки коллекции из файла.

Перегруженные операторы ввода/вывода представлены в листинге 3.6.

std::ostream& operator << (std::ostream& stream, TCollection& col)

{(unsigned i=0; i<col.size; i++)

//сначала выводится номер элемента в коллекции, потом тип, потом вызывается

//дружественный оператор << класса TObject<<'['<<i<<"]: "<<col.ppObjects[i]->ClassName()<<": "<<*col.ppObjects[i]<<'\n';stream;

}::istream& operator >> (std::istream& stream, TCollection& col)

{

char className[256];

stream>>className;//считываем из консоли строку с именем класса

//далее пытаемся создать объект с подходящим типом

TObject *p=NULL;(strcmp(className,"TInteger")==0)=new TInteger;if(strcmp(className,"TNumber")==0)=new TNumber;

if(p!=NULL)//если создать удалось

{

stream >>*p;//считываем сам объект с помощью перегруженного оператора

col.Add(p);//добавить в таблицу указатель на объект

}stream;

}

Листинг 3.6 Перегруженные дружественные операторы ввода/вывода в поток.

интерфейс класс таблица полиморфизм

3.     
Пример работы программы


Ниже, на рисунке 1, представлен скриншот коллекции разно типовых объектов. Сначала данные загружаются из ранее созданного файла output.txt. Далее происходит добавление и модификация элементов.

Рис. 1 Пример коллекции объектов.

ЗАКЛЮЧЕНИЕ

В результате выполнения работы был подробно изучен механизм работы виртуальных функций. Очевидным преимуществом механизма является возможность реализовать концепцию полиморфизма удобными средствами. Недостатком - наличие таблицы виртуальных методов требует дополнительную память, а также увеличения времени при вызове виртуально функции, т.к. доступ к ней происходит не сразу, а только после разыменовывания указателя, что замедляет вызов.

Похожие работы на - Таблица данных произвольных типов в памяти

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!