
- •Лабораторная работа 1
- •Методы (функции-члены) класса. Инкапсуляция Краткие справочные сведения
- •Задания к лабораторной работе 1
- •Лабораторная работа 2 Наследование и виртуальные функции. Абстрактные классы. Краткие справочные сведения
- •Задания к лабораторной работе 2
- •Лабораторная работа 3 Полиморфизм. Перегрузка операций и функций Краткие справочные сведения
- •Задания к лабораторной работе 3
- •Лабораторная работа 4 Дружественные функции Краткие справочные сведения
- •Void ff(...) тело функции .
- •Задания к лабораторной работе 4
Лабораторная работа 1
Классы и объекты в языке С++. Конструкторы и деструкторы.
Методы (функции-члены) класса. Инкапсуляция Краткие справочные сведения
Классы в языке С++ представляют собой механизм для создания объектов. Синтаксис описания класса:
class <имя класса>
{<закрытые функции и переменные класса>
public:
<открытые функции и переменные класса>
} [список объектов] ;
В описании класса <список объектов> не является обязательным. Функции и переменные, объявленные внутри класса, становится членами этого класса. В объявлении класса используются следующие спецификаторы: public, private, protected. Режим рublic обеспечивает возможность доступа к функции, объявленной после этого ключевого слова, из других функций программы. Режим private устанавливается по умолчанию и означает закрытость переменных и функций, объявленных после этого ключевого слова. К таким переменным закрыт доступ из других функций программы, кроме функций данного класса. Спецификатор protected указывает, что элементы-данные и элементы-функции доступны для функций и элементов данного класса и производных от него классов.
Для объявления объектов нужно указать имя класса и их список, например:
myclass ob1, ob2;
Общая форма задания функции:
<Тип> <имя класса> :: <имя функции>(<список параметров>)
{ ... // тело функции }
Пример. Найти середину отрезка по введенным координатам его концов с использованием обязательных функций-членов класса для ввода координат, нахождения середины, вывода отрезка в графическом режиме, расчета новых координат при повороте отрезка на заданный угол. Этот пример может применяться также для моделирования вращения прямой вокруг своей середины.
#include <iostream.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <graphics.h>
#define PI 3.1415
char ch; // глобальная переменная ch
class otr
{ int x,y,x1,y1,sx,sy; // описание класса otr
public:
void input();
void show();
void sered();
void povorot();
};
void otr :: input() // описание функции input
{ textcolor(YELLOW);
clrscr();
cout << "Введите целые координаты отрезка:\n";
cout << "в пределах: x(200,500) y(100,300) \n";
cin >> x >> y >> x1 >> y1;
}
void otr::sered() // описание функции sered
{ sx = (int)((x+x1)/2);
sy = (int)((y+y1)/2);
}
void otr::show() // описание функции show
{ int grdr = DETECT,grmd;
initgraph(&grdr,&grmd,"C:\ BC\BGI");
setbkcolor(BLUE);
setcolor(WHITE);
setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
line(x, y, x1, y1);
circle(sx, sy, 3);
setlinestyle(1, 0, NORM_WIDTH);
setcolor(YELLOW);
line(sx, 0, sx, 480);
line(0, sy, 640, sy);
setcolor(GREEN);
circle(x, y, 2);
setcolor(RED);
circle(x1, y1,2);
ch = getch();
closegraph();
}
void otr::povorot() // описание функции povorot
{ float a = 0.0, r = 0.0, a1=0.0;
textcolor(YELLOW);
clrscr();
cout << "Введите вещественный угол : ";
cin >> a;
a = a*(PI/180);
a1 = atan2((float)(sy-y1),(float)(x1-sx)); // перевод старых координат
r = sqrt((x1-sx)*(x1-sx)+(sy-y1)*(sy-y1)); // в новые
x1 = (int)(sx+r*cos(a1+a));
y1 = (int)(sy-r*sin(a1+a));
x = (int)(sx-r*cos(a1+a));
y = (int)(sy+r*sin(a1+a));
}
void main() // Основная программа
{
clrscr();
otr obj;
obj.input();
obj.sered();
obj.show();
do
{ obj.povorot();
obj.show();
}
while (ch!=27);
}
При работе с объектами появляется необходимость в их инициализации. Для решения этой проблемы язык С++ предоставляет функцию, включаемую в описание класса. Конструктор класса вызывается всякий раз при создании объекта этого класса, т.е. необходимая объекту инициализация выполняется автоматически. Конструктор имеет то же имя, что и класс, и не имеет возвращаемого значения.
Деструктор – это функция обратная конструктору. Он вызывается при удалении объекта. Например, при создании объекта для него выделятся память, которую нужно освободить при его удалении. Для этого в объявление класса включается деструктор, описание которого задается символом «~» с последующим именем класса.
Пример класса с конструктором и деструктором:
#include <iostream.h>
class myclass
{ int a;
public:
myclass(); // конструктор
~myclass(); // деструктор
void show();
};
myclass:: myclass() // определение конструктора
{ cout << "В конструкторе \n";
a = 10;}
myclass ::~myclass() // определение деструктора
{ cout << "Удаление...\n"; }
void myclass :: show()
{ cout << a; } // определение функции вывода a
void main()
{ myclass ob;
ob.show();
}
В этом примере значение a инициализируется конструктором myclass(). Конструктор вызывается тогда, когда создается объект ob. Деструктор же вызывается при удалении объекта.
Для глобальных объектов конструктор объектов вызывается тогда, когда начинается выполнение программы. Для локальных объектов конструктор вызывается всякий раз при выполнении оператора, объявляющего переменную.
Конструктору можно передать аргументы. Для этого надо добавить необходимые параметры в объявление и определение конструктора. Затем, при объявлении объекта, задать параметры в качестве аргументов. Показанная ниже программа демонстрирует передачу параметров в конструктор:
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
class strtype
{ char *p;
int len;
public:
strtype(char *ptr); //конструктор с параметром
~strtype(); //деструктор
void show();
};
strtype::strtype(char *ptr)
{ len = strlen(ptr);
p = new char[len + 1];
if(!p) { cout << "Ошибка выделения памяти";
exit(1); }
strcpy(p, ptr);
}
strtype::~strtype()
{ cout << "Освобождение p \n";
delete [] p; }
void strtype::show()
{ cout << p << "-длина: " << len;
cout << "\n"; }
void main()
{ strtype s1("Это проверка"), s2("Мне нравится С++");
clrscr();
s1.show();
s2.show();
getch();
}
Фактически синтаксис передачи аргумента конструктору с параметром является сокращенной формой записи следующего более длинного выражения:
myclass ob = myclass(4, 5); ( вместо myclass ob(4,5) )
Перегрузка конструкторов иллюстрируется следующим примером.
#include <iostream.h>
#include <conio.h>
class myclass
{ int x, y;
public: // перегрузка конструктора двумя способами
myclass() { x = 0; y = 0; } // нет инициализации
myclass(int n, int m) { x = n, y = m; } // инициализация
void show() { cout << x << ' ' << y << '\n'; } };
void main()
{ myclass o1[5]; // объявление массива без инициализации
myclass o2[5] =
{ myclass(1, 2),
myclass(3, 4),
myclass(5, 6), // объявление с инициализацией
myclass(7, 8),
myclass(9, 10), };
int i;
clrscr();
for(i = 0; i<5; i++) { o1[i].show(); cout << '\t' ; o2[i].show(); }
getch();
}
Одной из форм перегружаемого конструктора является конструктор копирования. Он используется при передаче объектов в функции, когда передается побитовая копия объекта в качестве параметра функции.