- •1. Абстрактные типы данных
- •Пример 1
- •1.4. Разработка объектов
- •1.4.1. Объекты и композиция
- •Пример 3
- •1.4.3. Объекты и наследование
- •1.4.4. Наследование в программировании
- •1.4.5. Упорядоченные списки и наследование
- •1.4.6. Повторное использование кода
- •1.4.7. Спецификации класса SeqList и OrderedList
- •1.5. Приложения с наследованием классов
- •1.6. Разработка объектно-ориентированных программ
- •1.6.1. Анализ задачи/определение программы
- •1.6.2. Разработка
- •1.6.3. Кодирование
- •1.6.4. Тестирование
- •1.6.5. Иллюстрация программной разработки: Dice график
- •Замечание
- •Программа 2. Диаграмма бросания костей
- •1.7. Тестирование и сопровождение программы
- •1.7.1. Объектное тестирование
- •1.7.2. Тестирование управляющего модуля
- •1.7.3. Программное сопровождение и документирование
- •1.9. Абстрактные базовые классы и полиморфизм
- •1.9.1. Полиморфизм и динамическое связывание
- •2.1. Пользовательский тип — класс
- •2.1.1. Объявление класса
- •Пример 1.
- •2.1.2. Конструктор
- •2.1.3. Объявление объекта
- •2.1.4. Реализация класса
- •2.1.5. Реализация конструктора
- •2.1.6. Создание объектов
- •Пример 2.
- •2.2. Примеры классов
- •2.2.1. Класс Temperature
- •2.2.2. Реализация класса Temperature
- •2.2.3. Класс случайных чисел
- •Пример 3.
- •2.2.4. Реализация класса RandomNumber
- •2.3. Объекты и передача информации
- •2.3.1. Объект как возвращаемое значение
- •2.3.2. Объект как параметр функции
- •2.4. Массивы объектов
- •2.4.1. Конструктор умолчания
- •2.5. Множественные конструкторы
- •2.5.1. Реализация класса Date
- •2.6. Практическое применение: Треугольные матрицы
- •2.6.1. Свойства верхней треугольной матрицы
- •2.6.2. Хранение треугольной матрицы
- •Пример 4.
- •Пример 5.
- •2.6.3. Класс TriMat
- •2.6.5. Реализация класса TriMat
Пример 4.
С учетом того, что элементы треугольной матрицы сохраняются построчно в массиве М, функция доступа для Ai,j использует следующие параметры:
Индексы i и j,
Массив rowTable
Алгоритм доступа к элементу Ai,j заключается в следующем:
Если j<i, Ai,j = 0 и этот элемент не сохраняется.
Если j³i, то получается значение rowTable[i], являющееся количеством элементов, которые сохраняются в массиве М, для элементов до строки i. В строке i первые i элементов являются нулевыми и не сохраняются в М. Элемент Ai,j помещается в M[rowTable[i]+(j-i)].
Пример 5.
Рассмотрим треугольную матрицу Х[3][3] из примера 3.4:
1.Х0,2 =M[rowTable[0]+(2-0)]=М[0+2]=М[2]=0
2.X1,0 не сохраняются
3.Х1,2 =M[rowTable[l]+(2-1)]=М[3+1]=М[4]=1
2.6.3. Класс TriMat
Класс TriMat реализует ряд операций треугольной матрицы. Вычитание и умножение треугольной матрицы оставлены для упражнений в конце главы. Учитывая то ограничение, что мы должны использовать только статические массивы, наш класс ограничивает размер строки и столбца числом 25. При этом мы будем иметь 300=(252-25)/2 нулевых элементов, поэтому массив М должен содержать 325 элементов.
Спецификация класса TriMat
ОБЪЯВЛЕНИЕ
#include <iostream.h>
#include <stdlib.h>
// максимальное число элементов и строк
// верхней треугольной матрицы
const int ELEMENTLIMIT = 325;
const int ROWLIMIT = 25;
class TriMat
{
private:
// закрытые данные-члены
int rowTable[ROWLIMIT]; // начальный индекс строки в М
int n; // размер строки/колонки
double М[ELEMENTLIMIT];
public:
// конструктор с параметрами TriMat(int matsize);
// методы доступа к элементам матрицы
void PutElement (double item, int i, int j);
double GetElement(int i, int j) const;
// матричные арифметические операции
TriMat AddMat(const TriMat& A) const;
double DelMat(void) const;
// матричные операции ввода/вывода
void ReadMat(void);
void WriteMat(void) const;
// получить размерность матрицы
int GetDimension(void) const;
};
ОПИСАНИЕ
Конструктор принимает число строк и столбцов матрицы. Методы PutEle-ment и GetElement сохраняют и возвращают элементы верхней треугольной матрицы. GetElement возвращает 0 для элементов ниже диагонали. AddMat возвращает сумму матрицы А с текущим объектом. Этот метод не изменяет значение текущей матрицы. Операторы ввода/вывода ReadMat и WriteMat работают со всеми элементами матрицы n x n. Сам метод ReadMat сохраняет только верхне-треугольные элементы матрицы.
Пример
#include trimat.h // включить класс TriMat
TriMat A (10), В (10), С (10); // треугольные матрицы 10x10
A.ReadMat (); // ввести матрицы А и В
B.ReadMat () ;
С = A. AddMat (В); // вычислить С = А + В
C.WriteMat (); // печатать С
2.6.5. Реализация класса TriMat
Конструктор инициализирует закрытый член n параметром matsize. Таким образом задается число строк и столбцов матрицы. Этот же параметр используется для инициализации массива rowTable, который используется для доступа к элементам матрицы. Если matsize превышает ROWLIMIT, выдается сообщение об ошибке и выполнение программы прерывается.
// инициализация n и rowTable
TriMat::TriMat (int matsize)
{
int storedElements = 0;
// прервать программу, если matsize больше ROWLIMIT
if (matsize > ROWLIMIT)
{
cerr << "Превышен размер матрицы" << ROWLIMIT << "x" << ROWLIMIT << endl;
exit (1) ;
}
n = matsize;
// задать таблицу
for (int i = 0; i < n; i++)
{
rowTable [i] = storedElements;
storedElements += n - i;
}
}
Матричные методы доступа. Ключевым моментом при работе с треугольными матрицами является возможность эффективного хранения ненулевых элементов в линейном массиве. Чтобы достичь такой эффективности и все же использовать обычные двумерные индексы i и j для доступа к элементу матрицы, нам необходимы функции PutElement и GetElement для сохранения и возвращения элементов матрицы в массиве.
Метод GetDimension предоставляет клиенту доступ к размеру матрицы. Эта информация может использоваться для обеспечения того, чтобы методам доступа передавались параметры, соответствующие правильной строке и столбцу:
// возвратить размерность матрицы n
int TriMat::GetDimension(void) const
{
return n;
}
Метод PutElement проверяет индексы i и j. Если j ³ i, мы сохраняем значение данных в М, используя функцию доступа к матрице для треугольных матриц: Если i или j не находится в диапазоне 0 . . (n-1), то программа заканчивается:
// записать элемент матрицы [i,j] в массив М
void TriMat::PutElement (double item, int i, int j)
{
// прервать программу, если индексы элемента вне
// индексного диапазона
if ((i < 0 || i >= n) || (j < 0 |1 j >= n))
{
cerr << "PutElement: индекс вне диапазона 0—"<< n-1 << endl;
exit (1);
}
// все элементы ниже диагонали игнорируются if (j >= i)
M[rowTable[i] + j-i] = item;
}
Для получения любого элемента метод GetElement проверяет индексы i и j. Если i или j не находится в диапазоне 0…(n – 1), программа заканчивается. Если j<i, то элемент находится в нижней треугольной матрице со значением 0. GetElement просто возвращает несохраняемое значение 0. В противном случае, j³i, и метод доступа может возвращать элемент из массива М:
// получить матричный элемент [i, j] массива М
double TriMat::GetElement(int i, int j) const
{
// прервать программу, если индексы вне индексного диапазона
if ((i < 0 || i >= п) || (j < 0 |I j >= n))
{
cerr << "GetElement: индекс вне диапазона 0—"<< n-1 << endl;
exit (1);
}
if (j >= i)
// вернуть элемент, если он выше диагонали
return M[rowTable [i] + j-i];
else
// элемент равен 0, если он ниже диагонали
return 0;
}
Ввод/вывод матричных объектов. Традиционно, ввод матрицы подразумевает, что данные вводятся построчно с полным набором значений строк, и столбцов. В объекте TriMat нижняя треугольная матрица является нулевой и значения не сохраняются в массиве. Тем не менее, пользователю предлагается ввести эти нулевые значения для сохранения обычного матричного ввода.
// читать элементы матрицы построчно, клиент должен ввести
// все (n x n) элементов
void TriMat::ReadMat (void)
double item;
int i, j;
for(i = 0; i<n; i++) // сканировать строки
for(j = 0; j<n; j++) //для каждой строки сканировать столбцы
{
cin >> item; //читать [i, j ]-й элемент матрицы
PutElement (item, i, j ) ; // сохранить этот элемент
//построчная выдача в поток элементов матрицы
void TriMat::WriteMat (void) const
{
int i,j;
// установка режима выдачи
cout. setf (ios::fixed) ;
cout.precision (3) ;
cout.setf (ios::showpoint) ;
for (i =0; i < n; i++)
{
for (j = 0; j < n; j++)
cout << setw(7) << GetElement (i,j);
cout << endl;
}
}
Матричные операции. Класс TriMat имеет методы для вычисления суммы двух матриц и детерминанта матрицы. Метод AddMat принимает единственный параметр, который является правым операндом в сумме. Текущий объект соответствует левому операнду. Например, сумма треугольных матриц X и Y использует метод AddMat для объекта X. Предположим, сумма сохраняется в объекте Z. Для вычисления
Z = Х + Y используйте оператор
Z = X.AddMat(Y) ;
Алгоритм сложения двух объектов типа TriMat возвращает новую матрицу В с элементами Bi,j = CurrentObjectyi,j + Ai,j:
// возвращает сумму текущей и матрицы А.
// Текущий объект не изменяется
TriMat TriMat::AddMat (const TriMat& A) const
int i , j;
double itemCurrent, itemA;
TriMat B(A.n); // в В будет искомая сумма
for (i = 0; i < n; i++) // цикл по строкам
{
for (j = i; j < n; j++) // пропускать элементы ниже диагонали
{
itemCurrent=GetElement i, j );
itemA = A.GetElement (i, j );
B. PutElement (itemCurrent + itemA, i, j);
}
}
return B;
}
Метод DetMat возвращает детерминант текущего объекта. Возвращаемое значение - это действительное число, которое является произведением элементов диагонали. Полный текст кода для реализации класса TriMat можно найти в программном приложении.
Программа 3.5. Операции с классом TriMat
Тестовая программа иллюстрирует класс TriMat с операциями ввода/вывода, а также матричного суммирования и определения детерминанта. Каждая секция программы снабжена комментариями.
#include <iostream.h>
#include <iomanip.h>
#include "trimat.h" // включить класс TriMat
void main(void)
{
int n;
// задать размер однородной матрицы
cout << "Каков размер матрицы? ";
cin >> n;
// объявить три матрицы размером (n x n)
TriMat A(n), B(n), C(n);
// читать матрицы А и В
cout<<"Введите некоторую "<<n<<"х"<<n<<
"треугольную матрицу" << endl;
A.ReadMat();
cout << endl;
cout << "Введите некоторую " << n << " x " << n <<
" треугольную матрицу" << endl;
B.ReadMat();
cout << endl;
// выполнить операции и напечать результат
cout << "Сумма А + В" << endl;
С = A.AddMat(В);
C.WriteMat() ;
Cout << endl;
cout << "Детерминант А+В= " << С.DetMat () << endl;
/*
<Выполнение программы 3.5>
Каков размер матрицы? 4
Введите некоторую 4x4 треугольную марицу
12-45
0241
0037
0005
Введите некоторую 4x4 треугольную матрицу
1467
02612
0031
0002
Сумма А + В
2.000 6.000 2.000 12.000
0.000 4.000 10.000 13.000
0.000 0.000 6.000 8.000
0.000 0.000 0.000 7.000
Детерминант А+В= 336.000 */