русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Лабораторная работа №5


Дата добавления: 2015-07-09; просмотров: 869; Нарушение авторских прав


Тема: “Шаблонные классы”

Шаблонные классы предоставляют большие возможности, чем шаблонные функ­ции. В таком классе определяются все его данные и функции, а фактические типы об­рабатываемых данных задаются в качестве параметров позже, при создании объек­тов этого класса.

При создании шаблонных классов нужно обратить внимание на следующие возможности:

Ø Шаблон типа необходимо задавать также при определении функции после име­­­ни класса, для которого эта функция определяется. Шаблон типа задается в угловых скобках;

Ø При определении функции, ему должно в каждом случае предшествовать задание шаблонов типа со служебным словом template;

Ø При создании объектов шаблонного класса после имени класса в угловых скобках задается конкретизация типа шаблона, то есть имя встроенного типа или типа пользователя, например:

Array <int> iar, *piar;

Array <double> dar, *pdar;

Ø Дружественные функции также можно задавать в шаблонном классе по общим требованиям к дружественным функциям.

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

 

Используя классы, можно определить новые типы данных. Например, в языке С++ отсутствует такой тип, как множество, но его легко реа­лизовать с помощью шаблонно­го класса.

Рассмотрим понятие множество. Множество – это какой-то «черный ящик», в который можно поместить элемент данного множества, проверить его наличие в множестве, исключить какой-либо элемент из множества. Будем считать, что все элементы множества должны быть уникальны (т.е. могут входить во множество только 1 раз). Порядок следования элементов во множестве не имеет значения, однако мы будем создавать множества элементов, упорядоченных по возрастанию.



Множество является подмножеством другого множества, если в этом другом множестве можно найти все элементы, имеющиеся в первом подмножестве. Например, множество {A, B} является подмножеством множества {A, B, C}.

Для множеств определены следующие операции:

Ø объединение множеств – это элементы, принадлежащие обоим множествам. Если A = {‘2’, ’4’, ’A’, ’B’, ’F’}, а B = {‘1’, ’4’, ’C’, ’B’, ’E’},то A + B = {‘2’, ’4’, ’A’, ’B’, ’F’, ‘1’, ‘C’, ‘E’};

Ø пересечение множеств – это те элементы, которые принадлежат одновременно обоим множествам A*B = {’4’, ’B’};

Ø разность множеств – это исключение из левого множества элементов, которые имеются в правом A – B = {‘2’, ’A’, ’F’};

Ø симметричная разность множеств – это набор элементов, которые входят только в одно из множеств (т.е. это объединение минус пересечение множеств): {‘2’, ’A’, ’F’, ‘1’, ‘C’, ‘E’}

Ø для множеств могут быть определены операции сравнения ==, !=, >=, <=, а также операция определения принадлежности элемента данному множеству.

Пример : Класс, описывающий множество.

В этом примере множество строится на основе линейного массива, память под который выделяется динамически.

 

#include <iostream>

#include <stdlib.h>

using namespace std;

#define DEFSET 100 // Размер множества по умолчанию

 

template <class Stype> class Set

// Stype – условное название типа элементов

{

Stype *SetPtr; // Указатель на члены множества

int MemSize; // Размер памяти, выделенный множеству

int NumMembers; // Количество элементов множества

 

// операторы ввода – вывода:

template<typename Stype> friend istream& operator>> (istream& stream, Set &ob);

template<typename Stype> friend ostream& operator << (ostream& stream, Set &ob);

 

// закрытые функции:

void insert(Stype member); // добавление элемента

void remove(Stype member); // удаление элемента

int find (Stype member); // возвращение индекса элемента

int ismember (Stype member);

//проверка, является ли элемент членом множества

 

//конструкторы и деструктор:

public:

Set();

Set (int size);

Set (const Set& ob);

~Set() { delete SetPtr;}

 

//Операторные функции:

Set<Stype>& operator = (const Set<Stype> &ob); // присваивание

Set<Stype>& operator + (Stype member); //Добавление нового элемента

template<typename Stype> friend Set<Stype> operator + (Stype member, Set& ob);

/* эта функция позволяет использовать операторы типа: s = 2 + s; функция не может быть членом класса, поскольку левый операнд – не объект этого класса */

Set<Stype> operator + (Set &ob); //Создание объединения

Set<Stype> operator - (Stype member); //Удаление элемента

Set<Stype> operator - (Set<Stype> &ob); //Разность множеств

int operator == (Set<Stype> &ob); // сравнение на равенство

int operator != (Set<Stype> &ob); // сравнение на неравенство

int operator < (Set<Stype> &ob); //1 - если подмножество

operator int () {return NumMembers;}

//операция преобразования к типу int

};

 

//определение функций:

 

template <class Stype> Set<Stype> :: Set() // конструктор по умолчанию

{

SetPtr = new Stype[DEFSET]; // используем размер по умолчанию

if (!SetPtr)

{

cout <<"Ошибка при размещении объекта в памяти.\n";

_getch(); exit(1);

}

NumMembers = 0; // множество пока пустое

MemSize = DEFSET;

}

 

/* основной конструктор (создает пустое множество c областью памяти заданного размера): */

template <class Stype> Set<Stype> :: Set(int size)

{

SetPtr = new Stype[size];

if (!SetPtr)

{

cout <<"Ошибка при размещении объекта в памяти.\n";

_getch(); exit(1);

}

NumMembers = 0;

MemSize = size;

}

 

// конструктор копирования:

template <class Stype> Set<Stype> :: Set(const Set<Stype> &ob)

{

MemSize = ob.MemSize;

SetPtr = new Stype[MemSize]; // выделяем память для копии

if (!SetPtr)

{

cout<<"Ошибка выделения памяти \n";

_getch(); exit(1);

}

NumMembers = ob.NumMembers;

for (int i=0; i<NumMembers; i++) // копируем элементы множества

SetPtr[i] = ob.SetPtr[i];

}

 

/* функция осуществляет поиск элемента во множестве и возвращает номер этого элемента; если элемент не найден, функция возвращает –1: */

template <class Stype> int Set <Stype> :: find (Stype member)

{

for (int i=0; i< NumMembers; i++)

if (SetPtr[i] == member) return i;

return -1;

}

 

// функция проверяет, входит ли элемент во множество:

template <class Stype>

int Set <Stype> :: ismember(Stype member)

{

if (find(member) != -1) return 1;

else return 0;

}

 

// Основная функция, которая добавляет элемент во множество:

template <class Stype> void Set <Stype> :: insert(Stype member)

{

if (NumMembers == MemSize) // если множество заполнено

{

Stype* tmp = new Stype[MemSize+10];

// выделяем новую память большего размера

// и копируем туда элементы:

for (int i =0; i< NumMembers; i++)

tmp[i] = SetPtr[i];

delete []SetPtr; // освобождаем ранее выделенную память

SetPtr = tmp; // настраиваем указатель на новую область памяти

}

if (! ismember(member)) // если элемент еще не входит во множество

{

int i=0;

// находим для него место:

while (i<NumMembers && SetPtr[i]<member) i++;

// сдвигаем элементы от этого места вправо:

for (int j = NumMembers-1; j>=i; j--)

SetPtr[j+1] = SetPtr[j];

SetPtr[i] = member; // вставляем элемент

NumMembers++;

}

}

 

// функция удаляет заданный элемент:

template <class Stype>

void Set<Stype> :: remove(Stype member)

{

int loc = find(member); // определяеи номер этого элемента

if ( loc != -1) // эсли элемент входит во множество

{ //

for(; loc<NumMembers-1; loc++)

SetPtr[loc] = SetPtr[loc+1]; // сдвигаем элементы влево

NumMembers--;

}

}

 

// функция ввода элементов:

template <class Stype>

istream& operator >> (istream& stream, Set<Stype> &ob)

{

Stype member;

int k;

cout << "Сколько элементов определить? ";

cin >> k;

cout << "Задайте элементы множества \n";

for (int i=0; i< k; i++)

{

cout << i+1 << " --> ";

stream >> member;

ob = ob + member;

// используем нижеследующую операторную функцию +

}

return stream;

}

 

// функция вывода:

template <class Stype>

ostream& operator << (ostream& stream, Set<Stype> &ob)

{

stream << "{ ";

for (int i=0; i<ob.NumMembers; i++)

stream << ob.SetPtr[i] << " ";

stream << " }" << endl;

return stream;

}

 

// Оператор присваивания:

template <class Stype>

Set<Stype>& Set<Stype>:: operator = (const Set<Stype>& ob)

{

// если выполняется самоприсваивание, функция завершает свою работу:

if (SetPtr == ob.SetPtr) return *this;

// в противном случае выполнчется копирование объекта ob:

MemSize = ob.MemSize;

delete []SetPtr;

SetPtr = new Stype[MemSize];

NumMembers = ob.NumMembers;

for (int i=0; i<NumMembers; i++)

SetPtr[i] = ob.SetPtr[i]; // копирование элементов

return *this ;

}

 

// операция добавления элемента к множеству:

template <class Stype>

Set<Stype>& Set<Stype>:: operator + (Stype member)

{

insert(member);

return *this;

}

 

/* дружественная функция (не член класса), которая добавляет элемент к множеству, если этот элемент является левым операндом операции: */

template <class Stype>

Set<Stype> operator + (Stype member, Set<Stype>& ob)

{

Set<Stype> temp(ob);

temp.insert(member);

return temp; // функция возвращает временный объект

}

 

template <class Stype>

Set<Stype> Set<Stype>::operator + (Set<Stype> &ob) //Объединение множеств

{

// создаем временный объект с достаточным объемом памяти:

Set<Stype> temp(MemSize + ob.MemSize);

for (int i=0; i<NumMembers; i++)

// копируем элементы первого множества

temp.insert(SetPtr[i]);

for (int i=0; i<ob.NumMembers; i++)

// копируем элементы второго множества

temp.insert(ob.SetPtr[i]);

return temp;

}

 

// Оператор, который удаляет заданный элемент из множества:

template <class Stype>

Set<Stype> Set<Stype>:: operator - (Stype member)

{

Set<Stype> temp(*this);

temp.remove(member);

return temp;

}

 

/* Функция удаляет из первого множества те элементы, которые есть во втором: */

template <class Stype>

Set<Stype> Set<Stype>:: operator - (Set<Stype>& ob)

{

Set<Stype> temp(*this);

for (int i=0; i < ob.NumMembers; i++)

if (ismember(ob.SetPtr[i]))

temp.remove(ob.SetPtr[i]);

return temp;

}

 

// функция определяет, является ли левое множество подмножеством правого:

template <class Stype>

int Set<Stype>:: operator < (Set<Stype> &ob)

{

for(int i=0; i<NumMembers; i++)

if (!ob.ismember(SetPtr[i])) return 0;

return 1;

}

 

// сравнение на равенство:

template <class Stype>

int Set<Stype>:: operator == (Set<Stype> &ob)

{

if (NumMembers != ob.NumMembers) return 0;

return *this < ob; /* Если размеры множеств равны и одно из множеств является подмножеством другого, то множества равны */

}

 

// операция !=

template <class Stype>

int Set<Stype>:: operator != (Set<Stype> &ob)

{

return !(*this == ob); // Используем ранее определенную операцию ==

}

 

// файл templset.cpp:

#include <iostream>

#include <conio.h>

#include <windows.h>

#include "templset.h"

using namespace std;

 

int main()

{

//Настройки шрифтов и региональных стандартов:

if(SetConsoleCP(1251)==0)

//проверка правильности установки кодировки символов для ввода

{

cerr<<"Fialed to set codepage!"<<endl;

/* если не удалось установить кодовую страницу, вывод сообщения об ошибке */

}

if(SetConsoleOutputCP(1251)==0)//тоже самое для вывода

{

cerr<<"Failed to set OUTPUT page!"<<endl;

}

Set <int> s;

cin >> s;

cout << s;

s = s + 1 + 3 + -1;

cout << "Добавили 1, 3, -1: \n" ;

cout << s;

s = 5 + s;

cout << "Прибавили 5 слева: \n";

cout << s;

s = s - (-1);

cout << "Удалили -1:\n";

cout << s;

Set<int> ss;

ss = ss + 1 + 5 + 10;

cout << "Второе множество:" ;

cout << "ss = " << ss;

Set<int> s2 = s + ss;

cout << "Объединение множеств:\n";

cout << "s2 = " << s2;

cout << "Размер объединения: ";

cout << int(s2)<< endl;

cout<< "Разность множеств:\n";

cout << s - ss;

if (s==ss) cout <<"Множества равны\n";

else cout << "Множества не равны\n";

_getch();

return 0;

}



<== предыдущая лекция | следующая лекция ==>
Задания для самостоятельного выполнения | Задания для самостоятельного выполнения


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 2.238 сек.