Алгоритмы библиотеки стандартных шаблонов

Алгоритм   Назначение  
adjacent_find     binary_search     copy   copy_backward     count     count_if     equal   equal_range   fill   find     find_end   find_first_of     find_if   for_each   generate generate_n   includes   inplace_merge     iter_swap     lexicographical_compare   lower_bound     make_heap     max   max_element     merge     min   min_element     mismatch   next_permutation     nth_element     partial_sort   partial_sort_copy     partition     pop_heap     prev_permutation   push_heap   random_shuffle   remove remove_if remove_copy remove_copy_if   replace replace jf replace_copy replace_copy_if   reverse reverse_copy   rotate rotate_copy   search     search_n     set_difference     set_intersection     set_symmetric_difference     set_union     sort   sort_heap   stable_partition   stable_sort   swap   swap_ranges   transform     unique unique_copy   upper_bound     Выполняет поиск смежных парных элементов в последовательности. Возвращает итератор первой пары   Выполняет бинарный поиск в упорядоченной после­довательности   Копирует последовательность   Аналогична функции сору(), за исключением того, что перемещает в начало последовательности эле­менты из ее конца   Возвращает число элементов в последовательности   Возвращает число элементов в последовательности, удовлетворяющих некоторому предикату   Определяет идентичность двух диапазонов   Возвращает диапазон, в который можно вставить элемент, не нарушив при этом порядок следования элементов в последовательности   Заполняет диапазон заданным значением   Выполняет поиск диапазона для значения и возвра­щает первый найденный элемент   Выполняет поиск диапазона для подпоследователь­ности. Функция возвращает итератор конца подпос­ледовательности внутри диапазона   Находит первый элемент внутри последовательно­сти, парный элементу внутри диапазона   Выполняет поиск диапазона для элемента, для кото­рого определенный пользователем унарный преди­кат возвращает истину   Назначает функцию диапазону элементов   Присваивает элементам в диапазоне значения, воз­ вращаемые порождающей функцией   Определяет, включает ли одна последовательность все элементы другой последовательности Выполняет слияние одного диапазона с другим. Оба диапазона должны быть отсортированы в порядке возрастания элементов. Результирующая последо­вательность сортируется   Меняет местами значения, на которые указывают два итератора, являющиеся аргументами функции   Сравнивает две последовательности в алфавитном порядке   Обнаруживает первое значение в последовательно­сти, которое не меньше заданного значения   Выполняет пирамидальную сортировку последова­тельности (пирамида, на английском языке heap, — полное двоичное дерево, обладающее тем свойст­вом, что значение каждого узла не меньше значения любого из его дочерних узлов.   Возвращает максимальное из двух значений   Возвращает итератор максимального элемента внутри диапазона   Выполняет слияние двух упорядоченных последова­тельностей, а результат размещает в третьей после­довательности   Возвращает минимальное из двух значений   Возвращает итератор минимального элемента внут­ри диапазона   Обнаруживает первое несовпадение между элемен­тами в двух последовательностях. Возвращает ите­раторы обоих несовпадающих элементов   Образует следующую перестановку (permutation) последовательности   Упорядочивает последовательность таким образом, чтобы все элементы, меньшие заданного элемента Б, располагались перед ним, а все элементы, боль­шие заданного элемента Е, — после него   Сортирует диапазон   Сортирует диапазон, а затем копирует столько эле­ментов, сколько войдет в результирующую последо­вательность   Упорядочивает последовательность таким образом, чтобы все элементы, для которых предикат возвра­щает истину, располагались перед элементами, для которых предикат возвращает ложь   Меняет местами первый и предыдущий перед по­следним элементы, а затем восстанавливает пира­МИДу   Образует предыдущую перестановку последова­тельности   Размещает элемент на конце пирамиды   Беспорядочно перемешивает последовательность   Удаляет элементы из заданного диапазона     Заменяет элементы внутри диапазона     Меняет порядок сортировки элементов диапазона на обратный     Выполняет циклический сдвиг влево элементов в диапазоне     Выполняет поиск подпоследовательности внутри последовательности   Выполняет поиск последовательности заданного числа одинаковых элементов   Создает последовательность, которая содержит раз­личающиеся участки двух упорядоченных наборов   Создает последовательность, которая содержит одинаковые участки двух упорядоченных наборов   Создает последовательность, которая содержит симметричные различающиеся участки двух упоря­доченных наборов   Создает последовательность, которая содержит объединение (union) двух упорядоченных наборов   Сортирует диапазон   Сортирует пирамиду внутри диапазона   Упорядочивает последовательность таким образом, чтобы все элементы, для которых предикат возвра­щает истину, располагались перед элементами, для которых предикат возвращает ложь. Разбиение на разделы остается постоянным; относительный поря­док расположения элементов последовательности не меняется Сортирует диапазон. Одинаковые элементы не пе­реставляются   Меняет местами два значения   Меняет местами элементы в диапазоне   Назначает функцию диапазону элементов и сохраня­ет результат в новой последовательности   Удаляет повторяющиеся элементы из диапазона   Обнаруживает последнее значение в последова­тельности, которое не больше некоторого значения
     

ПРИМЕР 1. Простейший класс. Объединение данных и методов





Создать объект «параллелепипед». Вычислить объем.

Поля объекта: длина, ширина, высота фигуры.

Первый принцип инкапсуляции: объединение данных и методов.

#include <iostream> // for cin cout

using namespace std;

class CBox // объявление класса

{

public: // спецификатор доступа

double m_length; // поле - длина

double m_width; // поле - ширина

double m_height; // поле - высота

double Volume( );//объявление метода – вычисление объема

};

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

double CBox::Volume()

{ return m_length * m_width * m_height;}

int main()

{

CBox mybox1;

// создание статического объекта (экземпляра класса)

// поля – public - нарушение второго принципа инкапсуляции

mybox1.m_length = 2; // инициализация полей !!!

mybox1.m_width = 3;

mybox1.m_height = 4;

cout << mybox1.Volume() << endl; //вычисление объема =24

//создание динамического объекта

// поля – public - нарушение второго принципа инкапсуляции

CBox *pmybox2 = new CBox;

pmybox2->m_length = 5; // инициализация полей !!!

pmybox2->m_width = 6;

pmybox2->m_height = 7;

// вычисление объема =210

cout << pmybox2->Volume() << endl;

delete pmybox2; // удаление динамического объекта

return 0;

}

ПРИМЕР 2. Доступ к данным через интерфейс

Пример тот же.

Второй принцип инкапсуляции: защита от внешнего вмешательства. Доступ к данным через интерфейс.

#include <iostream> // for cin cout

using namespace std;

class CBox // объявление класса

{ // по умолчанию спецификатор доступа private

double m_length; // поле - длина

double m_width; // поле - ширина

double m_height; // поле - высота

public: // спецификатор доступа

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

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

void Setlength(double sl)

{m_length = sl; }

void Setwidth(double sw)

{m_width = sw; }

void Setheight(double sh)

{m_height = sh; }

// доступ к полям через методы класса

double Getlength()

{return m_length;}

double Getwidth()

{return m_width;}

double Getheight()

{return m_height;}

double Volume( );//объявление метода – вычисление объема

// объявление перегруженного метода для вычисления объема

double Volume(CBox *);

};

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

double CBox::Volume()

{return m_length * m_width * m_height;}

// определение метода класса Volume()

// для демонстрации указателя this

double CBox::Volume(CBox * )

{return this->m_length * this->m_width * this->m_height;}

int main()

{ // создание статического объекта (экземпляра класса)

CBox mybox1;

// mybox1.m_length = 2; // ошибка !!!

// mybox1.m_width = 3; // ошибка !!!

// mybox1.m_height = 4; // ошибка !!!

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

mybox1.Setlength(2);

mybox1.Setwidth (3);

mybox1.Setheight(4);

cout<<mybox1.Getheight()<<" "<< mybox1.Volume()<< endl;

// 4 24

cout << mybox1.Volume(&mybox1) << endl;

// 24

// создание динамического объекта

CBox *pmybox2 = new CBox;

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

pmybox2->Setlength(5);

pmybox2->Setwidth(6);

pmybox2->Setheight(7);

cout<<pmybox2->Getlength()<<" "<<pmybox2->Volume()<<endl;

delete pmybox2; // удаление динамического объекта

return 0;

}

ПРИМЕР 3. Независимость интерфейса от реализации

Пример тот же. Меняем описание полей, определение методов. Главная программа не изменяется.

Независимость интерфейса от реализации, разрешаются только операции, определенные через интерфейс.

#include <iostream> // for cin cout

using namespace std;

class CBox // объявление класса

{

// по умолчанию спецификатор доступа private

double m_Size[3]; // поле - массив

public: // определение методов класса при объявлении

void Setlength(double sl)

{m_Size[0] = sl; }

void Setwidth(double sw)

{m_Size[1] = sw; }

void Setheight(double sh)

{m_Size[2] = sh; }

// доступ к полям через методы класса

double Getlength()

{ return m_Size[0]; }

double Getwidth()

{ return m_Size[1]; }

double Getheight()

{ return m_Size[2]; }

double Volume( ); // метод – вычисление объема

};

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

double CBox::Volume()

{ return m_Size[0] * m_Size[1] * m_Size[2]; }

// программа не изменяется

int main()

{

// создание статического объекта (экземпляра класса)

CBox mybox1;

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

mybox1.Setlength(2);

mybox1.Setwidth(3);

mybox1.Setheight(4);

cout<<mybox1.Getheight()<<" "<<mybox1.Volume()<< endl;

// 4 24

// создание динамического объекта

CBox *pmybox2 = new CBox;

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

pmybox2->Setlength(5);

pmybox2->Setwidth(6);

pmybox2->Setheight(7);

cout<<pmybox2->Getlength()<<" "<<pmybox2->Volume()<<endl;

delete pmybox2; // удаление динамического объекта

return 0;

}

ПРИМЕР 4. Конструктор, деструктор

Пример тот же. Добавляем конструктор, десруктор. Определение конструкторов при объявлении класса.

#include <iostream> // for cin cout

using namespace std;

class CBox // объявление класса

{

// по умолчанию спецификатор доступа private

double m_length; // поле - длина

double m_width; // поле - ширина

double m_height; // поле - высота

public:

CBox()//конструктор для инициализации полей значениями =0

{ m_length = 0; m_width = 0; m_height = 0; }

// перегруженный конструктор

// для инициализации двух полей значениями,

// третье поле инициализируется 0

CBox(double l, double w)

{ m_length = l; m_width = w; m_height = 0;}

// перегруженный конструктор для инициализации полей

CBox(double l, double w, double h)

{ m_length = l; m_width = w; m_height = h; }

~CBox () // деструктор

{ cout << "destructor CBox done"<<endl;}

void Print ()

{ cout<<" L = "<<m_length<<" W = "<<m_width<<

" H="<<m_height<<endl;

}

double Volume( )

{ return m_length * m_width * m_height; }

};

void main()

{ // вызов конструктора для инициализаци полей

// значениями 0 0 0

CBox mybox1;

mybox1.Print();

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

// значениями 1 2 3

CBox mybox2(1, 2, 3);

mybox2.Print();

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

// значениями 1 2 0

CBox mybox3(1, 2);

mybox3.Print();

// вызов стандартного конструктора копирования

CBox mybox4 = mybox2;

mybox4.Print();

// вызов стандарного конструктора копирования

mybox1 = mybox2;

mybox1.Print();

} // вызов деструктора

ПРИМЕР 5. Определение методов вне класса

Пример тот же. Определение конструкторов вне объявления класса.

#include <iostream> // for cin cout

using namespace std;

class CBox // объявление класса

{ // по умолчанию спецификатор доступа private

double m_length; // поле - длина

double m_width; // поле - ширина

double m_height; // поле - высота

public:

// конструктор для инициализации полей значениями =0

CBox();

// перегруженный конструктор для инициализации двух

// полей значениями, третье поле инициализируется 0

CBox(double l,double w);

// перегруженный конструктор для инициализации полей

CBox(double l, double w, double h);

~CBox (); // деструктор

void Print ()

{ cout <<" L = "<< m_length << " W = "<< m_width <<

" H = "<<m_height<<endl;

}

double Volume( )

{ return m_length * m_width * m_height; }

};

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

CBox:: CBox() : m_length(0), m_width(0), m_height(0) { }

CBox::CBox(double l,double w):

m_length(l), m_width(w), m_height(0) { }

CBox:: CBox(double l, double w, double h):

m_length(l), m_width(w), m_height(h){ }

// деструктор

CBox:: ~CBox ()

{cout << "destructor CBox done"<<endl; }

void main()

{

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

CBox mybox1;

mybox1.Print();

//вызов конструктора для инициализаци полей значениями 1 2 3

CBox mybox2(1, 2, 3);

mybox2.Print();

//вызов конструктора для инициализаци полей значениями 1 2 0

CBox mybox3(1, 2);

mybox3.Print();

// вызов стандартного конструктора копирования

CBox mybox4 = mybox2;

mybox4.Print();

// вызов стандарного конструктора копирования

mybox1 = mybox2;

mybox1.Print();

} // вызов деструктора

ПРИМЕР 6. Конcтантные поля, методы и объекты

#include <iostream> // for cin cout

using namespace std;

class CBox // объявление класса

{

double m_length; // поле - длина

double m_width; // поле - ширина

double m_height; // поле - высота

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

const int n; // число размерностей

public:

CBox();//конструктор для инициализации полей значениями =0

CBox(double l,double w); // перегруженные конструкторы

CBox(double l, double w, double h);

~CBox (); // деструктор

void Set_l(double l) { m_length = l;}

void Set_w(double w) { m_width = w;}

void Set_h(double h) { m_height = h;}

// константные методы не могут изменять поля класса

double Get_l() const { return m_length;}

double Get_w() const { return m_width;}

double Get_h() const { return m_height;}

void Print () const

{cout<< n << " L = " << m_length << " W = " << m_width <<

" H = "<< m_height << endl; }

double Volume( ) const

{ return m_length * m_width * m_height; }

};

// в определении конструкторов

// обязательна инициализация поля-константы

CBox:: CBox() :

m_length(0), m_width(0), m_height(0),n(3) { }

CBox:: CBox(double l,double w):

m_length(l), m_width(w), m_height(0),n(3) { }

CBox:: CBox(double l, double w, double h) :

m_length(l), m_width(w), m_height(h),n(3){ }

CBox:: ~CBox () // деструктор

{ cout << "destructor CBox done"<<endl; }

void main()

{

CBox mybox1(1, 2, 3);

mybox1.Print ();

mybox1.Set_l (4);

mybox1.Print();

cout<< mybox1.Get_l() <<endl;

const CBox mybox2(5, 6, 7); // константный объект

// mybox2.Print(); // запрещено !!!

// mybox2.Set_l(4); // запрещено !!!

// mybox2.Print(); // запрещено !!!

// cout<<mybox2.Get_l()<<endl; // запрещено !!!

CBox mybox3 = mybox2; // но !!!

mybox3.Print();

}

ПРИМЕР 7. Статические члены класса

В класс добавим статическую переменную m_noboxes и статический метод Getnoboxes(), позволяющий вернуть значение статической переменной.

Определение статической переменной обязательно вне класса.

Статические функции-члены класса имеют доступ только к статическим членам класса. Для доступа к нестатическим членам они должны получить адрес объекта как параметр

#include <iostream> // for cin cout

using namespace std;

class CBox // объявление класса

{

double m_length; // поле - длина

double m_width; // поле - ширина

double m_height; // поле - высота

static int m_noboxes; // поле - cтатическая переменная

public:

CBox() // конструктор

{m_length=0; m_width=0; m_height=0; m_noboxes++;}

// перегруженный конструктор

CBox(double l,double w)

{ m_length=l; m_width=w; m_height=0; m_noboxes++; }

// перегруженный конструктор

CBox(double l, double w, double h)

{m_length=l; m_width=w; m_height=h; m_noboxes++;}

~CBox () // деструктор

{ cout << "destructor CBox done"<<endl;}

void Set_l(double l) { m_length = l;}

void Set_w(double w) { m_width = w; }

void Set_h(double h) { m_height = h;}

const double Get_l() { return m_length;}

const double Get_w() { return m_width; }

const double Get_h() { return m_height;}

const void Print ()

{cout<<" L = " << m_length <<" W = "<< m_width<<

" H = "<< m_height <<endl;}

const double Volume( )

{ return m_length * m_width * m_height; }

// cтатические функции-члены класса имеют доступ

// только к статическим членам класса.

static int Getnoboxes()

{return m_noboxes;}

// для доступа к нестатическим членам они должны

// получить адрес объекта как параметр

static int Getnoboxes(CBox & C)

{C.Set_l(0);return m_noboxes;}

};

// определение статической переменной обязательно вне класса

int CBox::m_noboxes=0;

// значение статической переменной в примере равно

// количеству объектов описанного класса

void main()

{

CBox mybox1; // 1 объект

mybox1.Print();

cout<<mybox1. Getnoboxes ()<<endl;

CBox mybox2(1, 2); // 2 объект

mybox2.Print();

cout<<mybox1. Getnoboxes ()<<endl;

CBox mybox3(3, 4, 5); // 3 объект

mybox3.Print();

cout<<mybox1. Getnoboxes (mybox3)<<endl;

mybox3.Print();

}

ПРИМЕР 8. Массив объектов

Пример тот же. Создаем массив объектов данного класса.

#include <iostream> // for cin cout

using namespace std;

class CBox // объявление класса

{

double m_length; // поле - длина

double m_width; // поле - ширина

double m_height; // поле - высота

static int m_noboxes; // поле - cтатическая переменная

public:

CBox() // конструктор

{m_length = 0; m_width = 0; m_height = 0; m_noboxes++; }

CBox(double l,double w) // перегруженный конструктор

{m_length = l; m_width = w; m_height = 0; m_noboxes++; }

// перегруженный конструктор

CBox(double l, double w, double h)

{m_length = l; m_width = w; m_height = h; m_noboxes++; }

~CBox () // деструктор

{ cout << "destructor CBox done"<<endl; }

void Set_l(double l) { m_length=l;}

void Set_w(double w) { m_width=w;}

void Set_h(double h) { m_height=h;}

const double Get_l() { return m_length;}

const double Get_w() { return m_width;}

const double Get_h() { return m_height;}

const void Print ()

{ cout<<" L = "<<m_length<<" W = "<< m_width<<" H = "<<

m_height<<" m_noboxes = "<<m_noboxes<<endl;}

const double Volume( )

{ return m_length * m_width * m_height; }

// cтатические функции-члены класса имеют доступ

// только к статическим членам класса.

static int Getnoboxes() {return m_noboxes;}

// для доступа к нестатическим членам они должны

// получить адрес объекта как параметр

static int Getnoboxes(CBox &C)

{C.Set_l(0); return m_noboxes;}

};

// определение статической переменной обязательно вне класса

int CBox::m_noboxes=0;

// значение статической переменной в примере равно

// количеству объектов описанного класса

void main()

{ // массив объектов. конструктор по умолчанию!

CBox mybox[4];

cout<<" massiv1 "<<endl;

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

{

cout<<i<<endl;

mybox[i].Print();

}

// другой массив объектов. инициализация

CBox mybox1[3];

mybox1[0]=СBox();

mybox1[1]=CBox(1,2);

mybox1[2]=CBox(3,4,5);

cout<<" massiv2 "<<endl;

for(i = 0; i < 3; i++)

{

cout<<i<<endl;

mybox1[i].Print();

}

// или так массив объектов. инициализация

CBox mybox2[3]={CBox(),CBox(1,2),CBox(3,4,5)};

cout<<" massiv3 "<<endl;

for(i = 0; i < 3; i++)

{

cout<<i<<endl;

mybox2[i].Print();

}

}

ПРИМЕР 9. Стандартный конструктор копирования

Использование стандартного конструктора копирования.

#include <iostream> // for cin cout

using namespace std;

class CPoint

{

short m_a; // поле 1

short m_k; // поле 2

public:

CPoint()

{m_a = 4; m_k = 1;} // конструктор

~CPoint() {} // деструктор

void Setk(short k) {m_k=k;} // инициализация поля 2

void Seta(short a) {m_a=a;} // инициализация поля 1

void Print () // вывод значений полей на экран

{ cout << " a = "<< m_a << " k = " << m_k <<endl;}

};

int main()

{ // вызов конструктора – инициализация полей объекта х

CPoint x;

x.Print(); // 4 1

// вызов стандартного конструктора копирования

CPoint y = x;

y.Print(); // 4 1

x.Setk(5); // инициализация поля 2

x.Seta(8); // инициализация поля 1

x.Print(); // 8 5

y.Print(); // 4 1

return 0;

}

ПРИМЕР 10. Стандартный конструктор копирования не работает

Стандартный конструктор копирования нельзя использовать, если Вы работаете с членами – указателями.

#include <iostream> // for cin cout

using namespace std;

class CPoint

{

short m_a; // поле 1

short *m_k; // поле 2

public:

CPoint() // конструктор

{ m_a = 4;

m_k = new short(1);

}

~CPoint() {} // деструктор

void Setk(short k)

{*m_k = k;} // инициализация значения поля 2

void Seta(short a)

{m_a = a; } // инициализация поля 1

void Print () // вывод значений полей на экран

{ cout<<" a = "<<m_a<<" k = "<< *m_k<<" "<<m_k<<endl; }

};

int main()

{

// вызов конструктора – инициализация полей объекта х

CPoint x;

x.Print(); // 4 1

// вызов стандартного конструктора копирования

CPoint y = x;

y.Print(); // 4 1

x.Setk(5); // инициализация значения поля 2

x.Seta(8); // инициализация поля 1

x.Print(); // 8 5

y.Print(); // 4 5 !!! но должно быть 4 1

return 0;

}

ПРИМЕР 11. Собственный конструктор копирования

Определение собственного конструктора копирования.

#include <iostream> // for cin cout

using namespace std;

class CPoint

{

short m_a; // поле 1

short *m_k; // поле 2

public:

CPoint() // конструктор

{ m_a = 4;

m_k = new short(1);

}

// собственный конструктор копирования

CPoint ( CPoint &p)

{ m_a = p.m_a; m_k = new short(*p.m_k); }

~CPoint(){} // деструктор

void Setk(short k)

{*m_k = k;} // инициализация значения поля 2

void Seta(short a)

{m_a = a;} // инициализация поля 1

void Print () // вывод значений полей на экран

{cout << " a="<<m_a<<" k=" << *m_k<<" " << m_k<<endl;}

};

int main()

{

// вызов конструктора - инициализация полей

CPoint x;

x.Print(); // 4 1

// вызов собственного конструктора копирования

CPoint y (x);

y.Print(); // 4 1

x.Setk(5); // инициализация значения поля 2

x.Seta(8); // инициализация поля 1

x.Print(); // 8 5

y.Print(); // 4 1

return 0;

}

ПРИМЕР 12. Вложенные классы

Пример объявление вложенного класса.

#include <iostream> // for cin cout

using namespace std;

class Outer // объявление объемлющего класса

{

class Inner // объявление вложенного класса

{

int n;

public:

Inner(){ n = 0;} // конструктор вложенного класса

int count()

{ return ++n; } // метод вложенного класса

};

Inner n;

public:

// метод объемлющего класса

int count()

{ return n.count(); }

};

int main()

{

Outer n;

cout<<n.count()<<endl; // 1!!!

// Inner m; // нельзя!!!

// cout<<m.count()<<endl;

// Outer:: Inner m; // нельзя!!!

// cout<<m.count()<<endl;

return 0;

}

ПРИМЕР 13. Вложенные классы

Пример объявление вложенного класса доступного вне объемлющего класса.

#include <iostream> // for cin cout

using namespace std;

class Outer // объявление объемлющего класса

{

public:

class Inner // объявление вложенного класса

{

int n;

public:

Inner()

{ n = 0;} // конструктор вложенного класса

int count()

{ return ++n; } // метод вложенного класса

};

private:

Inner n;

public:

int count()

{return n.count();} // метод объемлющего класса

};

int main()

{

Outer n;

cout<<n.count()<<endl; // 1!!!

//Inner m; // нельзя!!!

//cout<<m.count()<<endl;

Outer:: Inner m;

cout<<m.count()<<endl; // 1!!!

return 0;

}

ПРИМЕР 14. Шаблон классов

Шаблон классов для одномерного массива размерности Size.

#include <iostream> // for cin cout

using namespace std;

template <class U = int, int Size = 100> // шаблон классов

class MyArray // объявление класса

{

U m_array [Size];

public:

MyArray(void) // конструктор

{ for (int i = 0; i <= Size - 1; i++)

m_array[i]=0;

}

~MyArray(void) {} // деструктор

// метод получения значения i элемента

U Get (int i);

// метод инициализации i элемента значением х

void Put (int i, U x);

// метод вывода элементов массива на экран

void Print()

{

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

cout << m_array[i] << " " ; cout<<endl;

}

};

// Определения методов

template <class U, int Size> // шаблон метода

U MyArray < U, Size>::Get (int i)

{

if (i < 0)

i = 0;

if (i > Size - 1)

i = Size - 1;

return m_array[i];

}

template <class U, int Size> // шаблон метода

void MyArray < U, Size>::Put (int i, U x)

{

if (i < 0)

i = 0;

if (i > Size - 1)

i = Size - 1;

m_array[i]=x;

}

int main()

{

//объект - массив из 5 вещественных элементов

MyArray <double, 5> darray;

// объект - массив из 100 целых элементов

MyArray <> iarray;

cout<<" darray = "<<endl;

darray.Print();

cout<<" iarray = "<<endl;

iarray.Print();

darray.Put(1,3.14);

iarray.Put(0,2);

darray.Put(0,iarray.Get(0));

cout<<" darray = "<<endl;

darray.Print();

return 0;

}

ПРИМЕР 15. Перегрузка операторов

Пример шаблона классов CVecn, позволяющего работать с n-мерными векторами, заданными своими координатами в прямоугольной системе координат. Внутренне представление этого вектора – одномерный массив элементов типа double размером n элементов.

#include <iostream> // for cin cout

using namespace std;

template <int Size = 3>

class CVecn // объявление класса

{

double m_array[Size]; // массив – поле класса

public:

// конструктор

CVecn (void)

{for (int i = 0; i < Size; i++)

m_array[i]=0;

}

~CVecn (void) {} // деструктор

CVecn operator - (); // унарный –

// сложение векторов с замещением

CVecn operator +=(const CVecn &r);

// сложение векторов

CVecn operator +(const CVecn &r);

// вычитание векторов с замещением

CVecn operator -=(const CVecn &r);

// вычитание векторов

CVecn operator -(const CVecn &r);

// скалярное произведение

double operator *(const CVecn &r);

// умножение вектора на скаляр

CVecn operator *(double l);

// умножение скаляра на вектор

friend CVecn operator *(double l,CVecn &r)

{ return r*l; }

// логическая операция равенства векторов

bool operator ==(const CVecn &r);

// логическая операция неравенства векторов

bool operator !=(const CVecn &r);

// оператор индексирования

// позволяет обращаться к элементам массива

// не нужны функции для доступа к полям (типа Set или Get).

double& operator [] (const int i);

};

// унарный -

template <int Size>

CVecn<Size> CVecn<Size>::operator -()

{

CVecn <Size> Result;

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

Result.m_array[i] =- m_array[i];

return Result;

}

// оператор индексирования

template <int Size>

double& CVecn <Size>::operator [](const int i)

{

if (i < 0)

return m_array[0];

if (i >= Size)

return m_array[Size - 1];

return m_array[i];

}

// сложение векторов с замещением

template <int Size>

CVecn <Size> CVecn <Size>::operator +=(const CVecn<Size> &r)

{

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

m_array[i] += r.m_array[i];

return *this;

}

// сложение векторов

template <int Size>

CVecn <Size> CVecn <Size>::operator +(const CVecn<Size> &r)

{

CVecn <Size> Rezult;

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

Rezult.m_array[i] = r.m_array[i] + m_array[i];

return Rezult;

}

//вычитание векторов с замещением

template <int Size>

CVecn <Size> CVecn <Size>::operator -=(const CVecn<Size> &r)

{

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

m_array[i] -= r.m_array[i];

return *this;

}

// вычитание векторов

template <int Size>

CVecn <Size> CVecn <Size>::operator -(const CVecn<Size> &r)

{

CVecn <Size> Rezult;

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

Rezult.m_array[i] = r.m_array[i] - m_array[i];

return Rezult;

}

// скалярное произведение

template <int Size>

double CVecn <Size>::operator *(const CVecn<Size> &r)

{

double sum = 0;

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

sum += m_array[i] * r.m_array[i];

return sum;

}

// умножение вектора на скаляр

template <int Size>

CVecn <Size> CVecn <Size>::operator *(double l)

{

CVecn <Size> Result;

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

Result.m_array[i] = m_array[i] * l;

return Result;

}

// логическая операция равенства векторов

template <int Size>

bool CVecn <Size>::operator ==(const CVecn<Size> &r)

{

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

if (m_array[i] != r.m_array[i])

return false;

return true;

}

// логическая операция неравенства векторов

template <int Size>

bool CVecn <Size>::operator !=(const CVecn<Size> &r)

{

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

if (m_array[i] != r.m_array[i])

return true;

return false;

}

/* // можно перегрузить оператор =

template <int Size>

CVecn<Size>& CVecn <Size>::operator =(const CVecn <Size> &r)

{

if (&r !=this)

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

m_array[i] = r.m_array[i];

return *this;

}

*/

// внешняя функция

// вывод элементов массива на экран

template <int Size>

void Print(CVecn <Size> vect)

{

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

cout << vect[i] << " " ;

cout<<endl;

}

int main()

{

const SIZE = 5;

// объявляем 3 объекта-вектора

CVecn <SIZE> vector1, vector2, vector3;

// инициализация 1 вектора

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

vector1[i] = i;

cout<<" vector1 = "<<endl;

Print(vector1);

// унарный минус

cout<<" -vector1= "<<endl;

Print(-vector1);

// инициализация 2 вектора

for (i = 0; i < SIZE; i++)

vector2[i] = i + 5;

cout<<endl<<" vector2 = "<<endl;

Print(vector2);

// сложение двух векторов с замещением

vector1 += vector2;

cout<<endl<<" vector1 += vector2 "<<endl; Print(vector1);

// сложение двух векторов

vector3 = vector1 + vector2;

cout<<endl<<" vector1 + vector2 = "<<endl; Print(vector3);

// умножение вектора на скаляр

vector1 = vector1 * 2;

cout<<endl<<" vector1 *= 2 "<<endl;

Print(vector1);

// умножение скаляра на вектор

vector1 = 2 * vector2;

cout<<endl<<" vector2 * 2 = "<<endl;

Print(vector1);

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

cout<<endl<<"vector1 == vector2 = "<<

(vector1 == vector2)<<endl;

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

cout<<endl<<" scalarnoe= "<<(vector1 * vector2)<<endl;

return 0;

}

ПРИМЕР 16. АТД - «комплексное число»

Создадим АТД для комплексных чисел.

// файл complex.h объявление класса

class CCmplx

{

double m_re; // действительная часть комплексного числа

double m_im; // мнимая часть комплексного числа

public:

// конструктор

CCmplx (double re = 0, double im = 0):

m_re(re), m_im(im){}

~CCmplx(void){} // деструктор

double & Re()

{return m_re;} // действ. часть

double & Im()

{return m_im;} // мнимая часть

double& operator [] (int i); // оператор []

// оператор ()

CCmplx& operator ()(double x = 0, double y = 0)

{ m_re = x;

m_im = y;

return *this;

}

CCmplx& operator = (CCmplx &r); // оператор =

CCmplx& operator = (double r); // оператор =

CCmplx operator - (); // оператор - унарный

CCmplx operator + (); // оператор + унарный

CCmplx operator ++ (); // prefix

CCmplx operator ++ (int); // postfix

CCmplx operator + (CCmplx &r); //+ два комплексных числа

CCmplx operator - (CCmplx &r); //- два комплексных числа

CCmplx operator *(CCmplx &r); //* два комплексных числа

CCmplx operator /(CCmplx &r); ///два комплексных числа

//комплексное + вещественное

CCmplx operator + (double r);

// комплексное - вещественное

CCmplx operator - (double r);

// комплексное * вещественное

CCmplx operator * (double r);

// комплексное / вещественное

CCmplx operator / (double r);

// + два комплексных числа c замещением

CCmplx operator += (CCmplx &r);

// - два комплексных числа c замещением

CCmplx operator -= (CCmplx &r);

// * два комплексных числа c замещением

CCmplx operator *=(CCmplx &r);

// / два комплексных числа c замещением

CCmplx operator /=(CCmplx &r);

// компл число + вещ. c замещением

CCmplx operator += (double r);

// компл число - вещ. c замещением

CCmplx operator -= (double r);

// компл число * вещ. c замещением

CCmplx operator *= (double r);

// компл число / вещ. c замещением

CCmplx operator /= (double r);

// сравнение компл. чисел на равенство

bool operator ==(CCmplx &r);

// сравнение компл. чисел на неравенство

bool operator !=(CCmplx &r);

// сравнение компл. числа с вещ. на равенство

bool operator ==(double r);

// сравнение компл. числа с вещ. на неравенство

bool operator !=(double r);

// вещ. + компл. число

friend CCmplx operator +(double l, CCmplx &r )

{ r.m_re = l + r.m_re;

return r;

}

// вещ. - компл. число

friend CCmplx operator -(double l, CCmplx &r )

{ r.m_re = l - r.m_re;

r.m_im = -r.m_im;

return r;

}

// вещ. * компл. число

friend CCmplx operator *(double l, CCmplx &r )

{ r.m_re = l * r.m_re;

r.m_im = l * r.m_im;

return r;

};

// вещ. / компл. число

friend CCmplx operator /(double l, CCmplx &r )

{ CCmplx z(l,0);

r = z / r;

return r;

}

// вещ. += компл. число

friend double operator +=(double l, CCmplx &r )

{ l = l + r.m_re;

return l;

}

// вещ. -= компл. число

friend double operator -=(double l, CCmplx &r )

{ l = l - r.m_re;

return l;

}

// вещ. *= компл. число

friend double operator *=(double l, CCmplx &r )

{ l = l * r.m_re;

return l;

};

// вещ. /= компл. число

friend double operator /=(double l, CCmplx &r )

{ CCmplx z(l,0);

z = z / r;

l = z.Re();

return l;

}

// сравнение вещ. числа с компл. на равенство

friend bool operator ==(double l, CCmplx &r)

{ return (r.m_re = l) && (r.m_im = 0)? true : false;}

// сравнение вещ. числа с компл. на неравенство

friend bool operator !=(double l, CCmplx &r)

{return (r.m_re != l) || (r.m_im != 0) ? true : false;}

// оператор >> для ввода компл. числа

friend istream& operator >> (istream &str, CCmplx &r)

{

double re = 0, im = 0;

str >> re >> im;

r = CCmplx(re, im);

return str;

}

// оператор << для вывода компл. числа

friend ostream& operator << (ostream& str, CCmplx &r)

{

if (r.m_im < 0)

return str<<r.m_re<<r.m_im<<"i";

else

return str << r.m_re << "+" << r.m_im << "i";

}

};

// файл complex.cpp определение методов

#include <iostream> // for cin cout

using namespace std;

#include "complex.h"

// если < …> файл следует искать в «стандартных include»

// если "…" файл следует искать в текущем каталоге

// оператор []

double& CCmplx:: operator [] (int i)

{ if (i <= 1)

return m_re;

else return m_im;

}

// оператор =

CCmplx& CCmplx:: operator = (CCmplx &r)

{ m_re = r.m_re;

m_im = r.m_im;

return *this;

}

// оператор =

CCmplx& CCmplx:: operator = (double r)

{ m_re = r;

m_im = 0;

return *this;

}

// оператор - унарный

CCmplx CCmplx:: operator - ()

{ m_re = -m_re;

m_im = -m_im;

return *this;

}

// оператор + унарный

CCmplx CCmplx:: operator + ()

{ return *this;}

// prefix

CCmplx CCmplx:: operator ++ ()

{ ++m_re;

return *this;

}

//postfix

CCmplx CCmplx:: operator ++ (int)

{ ++m_re;

return *this;

}

// + два комплексных числа

CCmplx CCmplx:: operator +(CCmplx &r)

{ CCmplx z(m_re + r.m_re, m_im + r.m_im);

return z;

}

// - два комплексных числа

CCmplx CCmplx:: operator - (CCmplx &r)

{ CCmplx z(m_re - r.m_re, m_im - r.m_im);

return z;

}

// * два комплексных числа

CCmplx CCmplx::operator *(CCmplx &r)

{ CCmplx z(m_re * r.m_re - m_im * r.m_im,

m_re * r.m_im + m_im * r.m_im);

return z;

}

// / два комплексных числа

CCmplx CCmplx::operator /(CCmplx &r)

{ double d = r.m_re * r.m_re + r.m_im * r.m_im;

CCmplx z((m_re * r.m_re + m_im * r.m_im) / d,

(m_im * r.m_re + m_re * r.m_im) / d);

return z;

}

// комплексное число + вещ.

CCmplx CCmplx:: operator + (double r)

{ CCmplx z(m_re + r, m_im);

return z;

}

// комплексное число – вещ.

CCmplx CCmplx:: operator - (double r)

{ CCmplx z(m_re - r, m_im);

return z;

}

// комплексное число * вещ.

CCmplx CCmplx:: operator * (double r)

{ CCmplx z(m_re * r, m_im * r);

return z;<

Наши рекомендации