
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ "САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ. ПРОФ. М. А. БОНЧ-БРУЕВИЧА"
Факультет инфокоммуникационных сетей и систем
Кафедра сетей связи и передачи данных
ЛАБОРАТОРНАЯ РАБОТА №5
«ШАБЛОНЫ КЛАССОВ»
по дисциплине «Объектно-ориентированное программирование»
Выполнил:
студент 2-го курса
дневного отделения
группы ИКПИ-92
Козлов Никита
Санкт-Петербург
2020
Постановка задачи
В настоящей лабораторной работе необходимо решить две задачи, связанные с организацией шаблонов классов. Первая из задач состоит в преобразовании в шаблон класс того числового класса, который был разработан студентом в первой лабораторной работе по ООП. Вторая задача состоит в разработке шаблона контейнера. При решении второй задачи следует предусмотреть обработку исключительных ситуаций.
Вариант второй задачи
Задача № 3.
Разработать шаблон класса для стека, построенного на основе массива с фиксированными размерами.
Файл vector.h
#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
#include <assert.h>
template <typename T>
class Vector
{
private:
size_t length = 0; // length of array
T* buffer = NULL; // array eq to null pointer
public:
Vector(); // Default constructor
Vector(const Vector& r); // Copy constuctor
Vector(int _length); // Constructor with given length
~Vector() { delete[] buffer; buffer = NULL; }; // Destructor
void print(); // Print each element of Vector array
size_t len(void) { return length; } // Returns legth of Vector array
template<typename U> friend U dot_product(const Vector<U>& v1, const Vector<U>& v2);
Vector operator = (const Vector& source);
Vector operator + (const Vector& other);
T& operator [] (const size_t index);
template<typename U> friend Vector<U> operator-(const Vector<U>& v1, const Vector<U>& v2);
};
#pragma region Vector objects
template <class T> Vector<T>::Vector()
{
Vector(20);
}
template <typename T> Vector<T>::Vector(int _length) :length(_length)
{
try
{
#pragma region exceptions
if (_length <= 0)
throw exception("Vector size cannot be equal to or less than zero");
#pragma endregion
buffer = new T[length];
for (size_t i = 0; i < length; i++)
buffer[i] = 0;
}
catch (const std::exception& ex)
{
cout << "[ERROR]: " << ex.what() << endl;
}
}
template <class T> Vector<T>::Vector(const Vector& arg) :length(arg.length)
{
buffer = new T[this->length];
for (size_t i = 0; i < arg.length; i++)
buffer[i] = arg.buffer[i];
}
template<class T> void Vector<T>::print()
{
cout << "{ ";
for (size_t i = 0; i < this->length; i++)
cout << "'" << buffer[i] << "' ";
cout << "}\n";
}
template<typename U> U dot_product(const Vector<U>& v1, const Vector<U>& v2)
{
try
{
U res = 0;
assert(v1.length == v2.length && throw exception("The arrays lengths must be equal"));
for (size_t i = 0; i < v1.length; ++i)
res += v1.buffer[i] * v2.buffer[i];
return res;
}
catch (const std::exception& ex)
{
cout << "[ERROR]: " << ex.what() << endl;
}
}
#pragma endregion
// Operators
#pragma region Vector operators
template<typename T>
Vector<T> Vector<T>::operator=(const Vector& source)
{
length = source.length;
buffer = new T[length];
for (size_t i = 0; i < length; i++)
buffer[i] = source.buffer[i];
return *this;
}
template <typename T>
Vector<T> Vector<T>::operator+(const Vector& arg)
{
try
{
#pragma region exceptions
if (length != arg.length)
{
throw exception("Vectors doesn't match by size");
}
#pragma endregion
Vector<T>temp(length);
for (size_t i = 0; i < length; i++)
temp.buffer[i] = buffer[i] + arg.buffer[i];
return temp;
}
catch (const std::exception& ex)
{
cout << "[ERROR]: " << ex.what() << endl;
exit(1);
}
}
template<typename T>
T& Vector<T>::operator[](const size_t index)
{
try
{
assert(index >= 0 && index < length && throw exception("Invalid array index"));
return buffer[index];
}
catch (const std::exception& ex)
{
cout << "[ERROR]: " << ex.what() << endl;
}
}
template<typename U>
Vector<U> operator-(const Vector<U>& v1, const Vector<U>& v2)
{
assert(v1.length == v2.length && "The array lengths must be equal");
Vector<U> temp(v1.length);
for (size_t i = 0; i < v1.length; i++)
temp.buffer[i] = v1.buffer[i] - v2.buffer[i];
return temp;
}
#pragma endregion
#endif // !VECTOR_H
Файл stack_t.h
#ifndef STACK_T_H
#define STACK_T_H
#include <iostream>
#define definit 0
using namespace std;
/// <summary>
/// Simple stack structure, based on limited array;
/// </summary>
template<typename T>
class stack_t
{
private:
// Buffer length
uint_fast32_t length;
T* buffer = NULL;
// Stack end pointer
uint_fast16_t end;
// Stack start pointer
uint_fast16_t start;
void indexide();
void reindexide();
public:
/// <summary>
/// Default stack_t constructor
/// </summary>
stack_t() { stack_t(5); };
/// <summary>
/// Stack_t constructor with given array size
/// </summary>
/// <param name="_length">Array length</param>
stack_t(uint_fast32_t _length);
// Stack_t destructor
~stack_t() { delete[]buffer; buffer = NULL;};
/// <summary>
/// Push argument on the top of the stack
/// </summary>
/// <param name="arg">- argument to push</param>
void push(T arg);
/// <summary>
/// Delte argument from the top of the stack
/// </summary>
void pop();
/// <summary>
/// Print all stack with formating
/// </summary>
void print();
/// <summary>
/// </summary>
/// <returns>true if stack empty</returns>
bool isEmpty();
/// <summary>
/// </summary>
/// <returns>true if stack full</returns>
bool isFull();
/// <summary>
///
/// </summary>
/// <returns>stack size</returns>
uint_fast32_t size();
};
#pragma region public
template<typename T>
inline stack_t<T>::stack_t(uint_fast32_t _length) :length(_length)
{
try
{
#pragma region exceptions
if (_length <= 0)
throw exception("stack size cannot be equal to zero");
#pragma endregion
buffer = new T[this->length];
for (uint_fast32_t i(0); i < this->length; i++)
this->buffer[i] = 0;
indexide();
}
catch (const std::exception& ex)
{
cout << "[ERROR]: " << ex.what() << endl;
}
}
template<typename T>
inline bool stack_t<T>::isEmpty()
{
if (this->buffer[end] == definit)
return true;
else
return false;
}
template<typename T>
inline bool stack_t<T>::isFull()
{
if (buffer[0] == definit)
return false;
else
return true;
}
template<typename T>
inline uint_fast32_t stack_t<T>::size()
{
return this->length;
};
template<typename T>
inline void stack_t<T>::push(T arg)
{
try
{
#pragma region exceptions
if (this->buffer == nullptr)
throw exception("buffer null pointer error");
if (this->buffer[0] != definit)
throw exception("Unable to place argument in stack because of overflow");
if (arg == 0)
throw exception("0 can't be a part of the stack");
#pragma endregion
if (isEmpty())
{
this->buffer[end] = arg;
reindexide();
}
else
{
for (size_t i(this->length); i != -1; --i)
{
if (this->buffer[i] == definit & this->buffer[i + 1] != definit)
{
this->buffer[i] = arg;
reindexide();
break;
}
}
}
}
catch (const std::exception& ex)
{
cout << "[ERROR]: " << ex.what() << endl;
}
}
template<typename T>
inline void stack_t<T>::pop()
{
this->buffer[start] = definit;
reindexide();
}
#pragma endregion
#pragma region private
template<typename T>
inline void stack_t<T>::indexide()
{
this->end = this->length - 1;
this->start = this->length - 1;
}
template<typename T>
inline void stack_t<T>::reindexide()
{
this->end = this->length - 1;
for (size_t i(0); i < length; i++)
{
if (buffer[i] != definit)
{
this->start = i;
break;
}
}
}
#pragma endregion
template<typename T>
inline void stack_t<T>::print()
{
try
{
#pragma region exceptions
if (this->buffer == nullptr)
throw exception("this->buffer was 0x1110112");
#pragma endregion
cout << "[";
for (size_t i(start); i < length; i++)
cout << " '" << this->buffer[i] << "' ";
cout << "]" << endl;
}
catch (const std::exception& ex)
{
cout << "[ERROR]: " << ex.what() << endl;
}
};
#endif // !STACK_T_H
Файл main.cpp
#include <iostream>
#include "Stack_t.h"
#include "vector.h"
using namespace std;
void main()
{
stack_t<int> a(3);
a.push(4);
a.print();
a.push(9);
a.print();
a.push(2);
a.print();
a.pop();
a.print();
Vector<int> b(5);
for (int i = 0; i < b.len(); i++)
b[i] = i + 2;
b.print();
}