Главная страница

Программирование C++. Пензенский государственный университет введение в программирование на языке с лабораторный практикум пенза 2010 г 2


Скачать 1.47 Mb.
НазваниеПензенский государственный университет введение в программирование на языке с лабораторный практикум пенза 2010 г 2
Дата06.10.2022
Размер1.47 Mb.
Формат файлаpdf
Имя файлаПрограммирование C++.pdf
ТипПрактикум
#718990
страница8 из 10
1   2   3   4   5   6   7   8   9   10

// Тестирование класса VECTOR1
#include
"vector1.h"
const
int
N = 5;
// Число векторов в массиве
int
main()
{ Создаем и инициализируем вектор v1 и массив векторов v_a, вызывается конструктор по умолчанию
VECTOR1
v1, v_a[N]; Задаем значения и печатаем массив векторов
for
(
int
i = 0; i < N; i++ )
{
v_a[i].Assign( i, i+1 );
cout<<
"\n Vector v_a["
<
"]:"
;
v_a[i].print( );
}
// К элементам массива векторов добавляем единичные вектора
// и печатаем массив
for
(
int
i = 0; i < N; i++ )
{
++v_a[i];
cout<<
"\n Vector v_a["
<
"]:"
;
v_a[i].print( );
}
// Вычисляем сумму элементов массива векторов и печатаем ее
for
(
int
i = 0; i < N; i++ )
{
v1 = v1 + v_a[i];
}
cout<<
"\n Summa - vector v1 : "
; v1.print( );
cout<
system(
"pause"
);
return
0;
}

62 Результат работы программы Наследование и полиморфизм Наследование позволяет классам- потомкам при сохранении всех свойств классов- родителей добавлять свои собственные свойства, которые отражают их индивидуальность. На рисунке 4.1 приведена диаграмма классов
Figure фигура, Circle окружность,
Rectangle прямоугольник. Рисунок 4.1 – Диаграмма классов

63 Класс
Figure
– базовый класс,
Circle и Rectangle
– наследуемые классы. Полиморфизм в С имеет две формы перегрузка операций, функций, использование шаблонов. В этом случае определение конкретного экземпляра операции, функции или класса выполняется на этапе компиляции и называется статическим связыванием использование виртуальных функций (основная форма полиморфизма. В этом случае определение конкретного экземпляра операции, функции или класса выполняется вовремя выполнения программы и называется динамическим связыванием. Рассмотрим пример реализации диаграммы классов (рисунок 4.1) с использованием наследования и виртуалных функций. В примере вместо реальных графических методов будем использовать сообщения, выводимые на консоль. Пример Иерархия классов Фигура, Окружность, Прямоугольник Файл fiures.h

// определение классов Фигура, Окружность,
//
Прямоугольник, их данных и методов
#ifndef
_FIGURES_H предотвращение многократного
#define
_FIGURES_H включения заголовочного файла
#include

using
std::endl;
using
std::cout;
class
Figure
// Базовый класс
{
// Методы
public
:
Figure(
void
)
// Конструктор по умолчанию
{
cout <<
"The constructor Figure"
<< endl;
}
virtual

Figure(
void
)
// Виртуальный деструктор
{
cout <<
"The destructor Figure"
<< endl;
}
// Нарисовать фигуру - чисто виртуальная функция
// не имеет реализации в базовом классе
virtual
void
draw(
void
) = 0;
};
class
Circle:
public
Figure
// Circle наследуется от Figure
{
// Данные
private
:
int
x,
// координата центра
y,
// координата центра
r;
// Радиус окружности

64
// Методы
public
:
Circle(
int
CenterX,
int
CenterY,
int
Radius )
// Конструктор
{
cout <<
"The constructor Circle"
<< endl;
x = CenterX; y = CenterY; r = Radius;
}
virtual
Circle(
void
)
// Виртуальный деструктор
{
cout <<
"The destructor Circle"
<< endl;
}
// Нарисовать фигуру - виртуальная функция
virtual
void
draw(
void
);
};
// Нарисовать окружность, реализация в классе Circle
void
Circle::draw(
void
)
{
cout <<
"The Circle draw"
<< endl;
}
class
Rectangle:
public
Figure
// Rectangle наследуется от Figure
{
// Данные
private
:
int
l,
// Левый верхний
t,
// угол
r,
// Правый нижний угол
b;
// прямоугольника
// Методы
public
:
Rectangle(
int
L,
int
T,
int
R,
int
B )
// Конструктор
{
cout <<
"The constructor Rectangle"
<< endl;
l = L; t = T; r = R; b = B;
}
virtual
Rectangle(
void
)
// Виртуальный деструктор
{
cout <<
"The destructor Rectangle"
<< endl;
}
// Нарисовать фигуру - виртуальная функция
virtual
void
draw(
void
);
};
// Нарисовать прямоугольник, реализация в классе Rectangle
void
Rectangle::draw(
void
)
{
cout <<
"The Rectangle draw"
<< endl;
}
#endif
_FIGURES_H

65 Файл der_virt1.cpp

// Тестирование классов Фигура, Окружность,
//
Прямоугольник
#include
"figures.h"
int
main()
// Тестирование классов Figure, Circle и Rectangle
{
// Создается массив указателей на базовый класс, который
// инициализируется адресами объектов классов Circle и Rectangle
Figure *figures[2];
figures[0] =
new
Circle( 100, 100, 10 );
figures[1] =
new
Rectangle( 100, 100, 200, 250 );
// Для каждого объекта базового класса вызывается метод рисования фигуры
figures[0]->draw();
figures[1]->draw();
// Уничтожаются созданные объекты. Если бы деструкторы небыли виртуальными, то при уничтожении объектов вызывался бы Figure( ) -
// деструктор базового класса, что приводило бык ошибке
delete
figures[0];
delete
figures[1];
cout<
system(
"pause"
);
return
0;
} Результат работы программы Обратите внимание на порядок вызова конструкторов сначала базового, а потом наследуемого класс с аи де стр ук торов сначала наследуемого класс с а , а потом базового. Использование виртуальных функций позволяет с помощью указателя на объект базового класса вызывать методы наследуемых классов (в примере
draw
) – это и есть полиморфизм

66 Примеры программ

4.4.1 Класс Одномерный динамический массив Данный класс содержит одномерный массив целых чисел, память для которых выделяется динамически. Использование динамической памяти требует глубинного (поэлементного) копирования в операциях присваивания с объектами данного класса. Поэтому в классе необходимо создать копирующий конструктор и перегрузить операцию присваивания. Для того, чтобы обеспечить повторное присваивание например,
a=b=c
) перегружаемая функция должна возвращать ссылку В классе реализуется безопасная операция индексирования, которая предотвращает обращение к элементам массива, номер которых выходит заграницы массива. Для того, чтобы операцию индексирования можно было использовать со бе их сторон при сваи в ни я , перегружаемая функция должна возвращать ссылку, ан е значение Для проверки корректности выполнения программы в реализации методов класса используется макрос выражение) из стандартной библиотеки assert.h. Если результат выражения, стоящего в скобках – ложь, то выполнение программы прерывается и выдается дианостическое сообщение. Пример Класс Одномерный динамический массив Файл DinArray1.h определение динамического массива и его операций Н предотвращение многократного

#define
Н включения заголовочного файла
#include
"assert.h"
#include

using
std::endl;
using
std::cout;
class
Array1D динамический одномерный массив
{ Данные
private
:
int
*p; указатель на первый элемент массива целых чисел
int
size; размерность массива Методы
public
:
Array1D(
int
n=3); конструктор по умолчанию(размерность массива = 3)
Array1D(
const
Array1D& a); копирующий конструктор
Array1D() {
delete
[] p;}
//деструктор освобождает память, выделенную
для массива
void
print()
const
; вывод значений элементов массива перегружаемые операции
int
&
operator
[](
int
i)
const
; индексирование
Array1D&
operator
=(
const
Array1D& a); присваивание
Array1D
operator
+(
const
Array1D& a)
const
; сложение (бинарная операция)
};

67 реализация методов класса
Array1D
Array1D::Array1D(
int
n) : size(n) конструктор по умолчанию
assert(n>0); размерность массива должна быть положительной
p=
new
int
[n];
//выделяем память для элементов массива
assert(p!=0);
//если память не выделена, то аварийное завершение
};
Array1D::Array1D(
const
Array1D& a) : size(a.size) копирующий конструктор
p=
new
int
[size]; выделяем память для элементов массива
assert(p!=0);
//если память не выделена, то аварийное завершение i=0; i
p[i] = a.p[i];
присваиваем значения элементам массива
void
Array1D::print()
const
{
for
(
int
i=0; i
cout<
cout<
}
int
& Array1D::
operator
[](
int
i)
const
{
assert( i>=0 && i
если индекс заграницами, то аварийное завершение p[i];
возвращаем ссылку на
i – й элемент массива
Array1D& Array1D::
operator
=(
const
Array1D& a)
{
if
(
this
!= &a){ если присваивание самому себе, то ничего делать не надо == a.size);
если размеры массивов неравны, то аварийное
завершение i=0; i
p[i] = a.p[i];
}
return
*
this
;
возвращаем ссылку на объект
Array1D
}
Array1D Array1D::
operator
+(
const
Array1D& a)
const
{
assert(size == a.size);
если размеры массивов неравны, то аварийное
завершение sum(size);
создаем массив
sum
размерности
size
for
(
int
i=0; i
sum.p[i] = p[i] + a.p[i];
// или sum.p[i]=this->p[i] +a.p[i];
return
sum;
сначала вызывается конструктор копирования потом деструктор массива
sum
e
}
#endif
Н

68 Файл DinArray1.cpp

// Тестирование класса Array1D
#include
"DinArray1.h"
int
main()
{
Array1D a, b, c; Размерность массивов по умолчанию = 3
for
(
int
i=0; i<3; ++i) a[i]=i+1; Инициализируем массива и выводим его значения
a.print();
b = a; Присваиваем элементам массива b значения элементов массива a
cout<<
"Array1D b: "
<
b.print();
a = a + b + (c = a + b); Сначала определяем значения с, затем увеличиваем значения а
cout<<
"Array1D c: "
<
c.print();
cout<<
"Array1D a: "
<
a.print();
system(
"pause"
);
return
0; Результат работы программы

69 4.4.2 Класс Динамически размещаемая срока Данный класс содержит строку произвольной длины, символы которой размещаются в памяти динамически. В реализации методов класса используются функции из стандартной библиотеки
<
cstring>:
strcpy_s(s, len, str)
– копирование не более
len символов из строки в строку
strcat_s(s, len, str)
– добавление не более
len символов из строки в строку

strlen(str)
– длина строки
str. Функция возвращает значение типа Функции
strcpy_s, strcat_s безопасные (контролируют число пересылаеых символов) по сравнению с функциями
strcpy, strcat, при использовании котрых компилятор выдает предупреждение
«This function or variable may be unsafe. Consider using strcpy_s instead.» Для проверки корректности выполнения программы в реализации методов класса используется макрос выражение) из стандартной библиотеки Пример Класс Динамически размешаемая строка Файл DinString.h определение динамической строки и операций Н предотвращение многократного
#define
Н включения заголовочного файла
#include

using
std::endl;
using
std::cout;
#include

#include
"assert.h"
class
DinString динамически размещаемая срока
{ Данные
private
:
char
*s; указатель на строку
int
len; длина строки Методы
public
:
DinString(): len(0){ конструктор по умолчанию
s=
new
char
[1]; assert(s!=0); s[0]=0;
}
DinString(
const
DinString& str); копирующий конструктор
DinString(
const
char
* str); преобразующий конструктор - преобразует тип char* к типу DinString
DinString() {
delete
[] s;}
//деструктор освобождает память,
// выделенную для строки
void
print()
const
{ вывод строки
// перегружаемые операции
DinString&
operator
=(
const
DinString& str); присваивание
DinString
operator
+ (
const
DinString& str)
const
; конкатенация
};

70 реализация методов класса DinString

DinString::DinString(
const
char
* str) преобразующий конструктор
{
len = преобразуем возвращаемое значение
// функции
strlen
типа
size_t в
// значение типа int
s=
new
char
[len+1]; выделяем память для строки
assert(s!=0); если память не выделена, то аварийное завершение
strcpy_s(s, len+1, str);
}
DinString::DinString(
const
DinString& str) : len(str.len) копирующий конструктор
{
s=
new
char
[len+1]; выделяем память для строки
assert(s!=0); если память не выделена, то аварийное завершение
strcpy_s(s, len+1, str.s);
}
DinString& DinString::
operator
=(
const
DinString& str)
{
if
(
this
!= &str){ если присваивание самому себе, то ничего делать не надо
delete
[] s; удаляем "старую" строку
len = str.len; формируем длину новой строки
s=
new
char
[len+1]; выделяем память для строки
assert(s!=0); если память не выделена, то аварийное завершение
strcpy_s(s, len+1, str.s);
}
return
*
this
; возвращаем ссылку на объект
}
DinString DinString::
operator
+ (
const
DinString& str)
const
{
DinString tmp;
tmp.s =
new
char
[len + str.len +1];
tmp.len=len + str.len;
1   2   3   4   5   6   7   8   9   10


написать администратору сайта