Алгоритмы библиотеки стандартных шаблонов
Алгоритм | Назначение | |
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;<