Використання класів

Наведемо програму, яка ілюструє принцип наслідування класів.

Приклад 11.5. Обчислити площу круга та поверхню циліндра, як­що задано радіус круга і висоту циліндра.

// Р11_5.СРР — наследование классов

#include<iostream.h>

#include<math.h>

#include <conio.h>

#define pi M_PI

inline float sqr(float x)

{ return x*x; }

class Circle           //---------------- базовый класс

{

protected:

float r;

public:

Circle(float rVal=0) { r=rVal; }

void setRadius(float rVal) { r=rVal; }

float Radius ()

{ return r; }

float Агеа()

{ return pi*sqr(r);

} /* функція вычисления площади круга */

void ShowData();

};

class Cylinder: public Circle //--- производный класс (наследник)

{

protected:

float h;

public:

Cylinder(float hVal=0, float rVaI=0) { h=hVal;

r = rVal; }

void set_h(float hVal)

{ h=hVal; }

float Height()

{ return h; }

float Area() /* функция вычисления поверхности цилиндра с использованием функции Агеа() базового класса */

{ return 2*Circle::Area() +2*pi*r*h; }

void ShowData();

};

void Circle::ShowData() {

cout << "Circle radius = "<<Radius()<<endl;

cout << "Circle area = "<<Area()<<"\n\n";

}

void Cylinder::ShowData() {

cout<<"Cylinder radius = "<<Radius()<<endl;

cout<<"Cylinder area = "<<Area()<<"\n\n";

}

int main() {

Circle crcl(5);

Cylinder cldr(10,7);

crcl.ShowData();

cldr.ShowData();

getch (); 
return 0;

Результат виконання програми:

Circle radius = 5

Circle area = 78.5398

Cylinder radius = 7

Cylinder area = 747.699

У програмі описано базовий клас Circle, в якому реалізу­ється функція визначення площі круга Агеа( ). У похідному класі Cilinder також є функція з ім’ям Агеа( ), що призначе­на для знаходження поверхні циліндра, причому в ній застосо­вується така ж функція базового класу, але вона записана як Circle:: Агеа( ), тобто з використанням операції розширення об­ласті свого класу.

Такі функції називаються поліморфними. Поліморфізм — це можливість для об’єктів різних класів, що пов’язані між со­бою завдяки успадкуванню, реагувати по-різному при зверненні до однієї і тієї ж функції-члену класу. Поліморфізм звичайно реалізується шляхом використання віртуальних функцій.

Якщо функція-член класу визначена у базовому класі, але перевизначена в похідному і викликається для виконання, то використовується версія цієї функції з базового класу. Але як­що ця функція оголошена віртуальною у базовому і похідному класах, то для її виконання застосовується форма, що відпо­відає своєму класу.

Приклад 11.6. Піднести до квадрата змінну х і отримане значення поділити на 2, далі змінну піднести до куба.

Проілюструємо цей приклад двома програмами. У першій з них (див. Р11_6_1.СРР) оголошено два класи: базовий mycl1 і похідний  mycl2. У базовому класі описані функцїї-члени fun1() і fun2(), одна з яких підносить до квадрата змінну х, а друга ді­лить одержане значення на 2.

У похідному класі також описано функцію fun1(), але вона підносить до куба, тобто перевизначає цю функцію з базового класу.

Головна програма має оголошений об’єкт р1 похідного кла­су, який, здавалося б, при виконанні функції fun2() повинен використовувати функцію funl() похідного класу, однак він ви­кликає таку функцію з базового класу.

// Р11__6_1.СРР — использование классов

#include <iostream.h>

#include <conio.h>

class mycl1

{

public:

float fun1 (float x) { return x*x; }

float fun2(float x) { return fun1(x)/2; }

};

class mycl2:public mycl1 {

public:

float funl(float x) { return x*x*x; }

};

main()

{ mycl2 p1;

cout << "pl.fun2(10)= " << p1.fun2(10) << endl;
getch (); 

return 0;

}

Результати виконання програми:

p1.fun2(10)= 50

У наступній програмі (див. Р11_6_2.СРР) функції fun1() ого­лошено віртуальними, тому одержимо інший результат.

// Р11_6_2.СРР — использование виртуальных функций

#include <iostream.h>

#include <conio.h>

class mycl1

{ public:

virtual float fun1(float x) { return x*x; }

float fun2(float x) { return fun1(x)/2; }

};

class mycl2:public mycl1 {

public:

virtual float funl (float x) { return x*x*x; }

};

main() {

mycl1 p1;

mycl2 p2;

cout << "p1.fun2(10)= "<<p1.fun2(10)<<endl;

cout << "p2.fun2(10)= "<<p2.fun2(10)<<endl;

getch (); 

return 0;

}

Результат розв’язання програми:

p1.fun2(10)= 50

p2.fun2(10)= 500

Віртуальна функція описується як звичайна, тільки перед її ім’ям записується словоvirtual.

Класи зручно використовувати при створенні власної біб­ліотеки модулів, призначених для розв’язання різних задач. У такому випадку описання класу розміщують в окремому фай­лі, ім’я якого записують з розширенням .h. У головній про­грамі, яку записують з окремим ім’ям і розширенням .срр, оголошують потрібні об’єкти і викликають необхідні для робо­ти функції-члени класу.

Приклад 11.7. Створити програму обчислення площ прямокутника і квадрата з використанням віртуальних функцій.

У програмі при визначенні площі прямокутника для пра­вильного використання ширини відповідні функції Width() ба­зового і похідного класів оголошено віртуальними.

// Р11_7.СРР — использование виртуальных функций

#include <iostream.h>

#include <conio.h>

class Square {

protected: float length;

public:

Square (float len) { length=len; }

float Length() { return length; }

virtual float Width { return length; }

float Area() { return Length()*Width(); }

};

class Rectangl : public Square {

protected: float width;

public:

Rectangl (float len, float wide):

Square(len), width(wide) { }

virtual float Width() { return width; }

};

main()

{

Square sq(10);

Rectangl rec(10,12);

cout<<" For square len = "<<sq.Length() <<endl <<"Area= "<<sq.Area()<<endl;

cout<<" For rectangle len = "<<rec.Length()<<endl<< "width= "<<rec.Width()<<endl <<"Area= "<<rec.Area()<<endl;

getch (); 

return 0;

}

Результат розв’язання програми:

For square len = 10

Area= 100

For rectangle len = 10

width = 12

Area= 120

Приклад 11.8. Створити файл Tmassiv.h, який має функцію вве­дення масиву, та залежно від завдання відсортувати цей масив за спа­данням або за зростанням елементів.

// Р11_8.СРР — создание файла ("Tmassiv.h"), содержащего функции

#include <iostream.h>

class Tmassiv

{

float *ptr;

int sz;



У програмі описано клас Tmassiv, в якому створюється ма­сив, що потім обробляється і виводиться на екран. Клас Tmassiv містить:

  • покажчик *ptr — для створення масиву;
  • змінну sz — для фіксування розміру масиву;
  • конструктор класу, в якому виділяється динамічна пам’ять для розміщення масиву та ініціюється його розмір;
  • деструктор класу, який організує звільнення динамічної пам’яті;
  • функції-члени класу:

fsize() — для повернення розміру масиву;

vvod() — для введення значень елементів масиву;

vivod() — для виведення елементів масиву на екран;

sort() — для сортування масиву за зростанням або за спа­данням значень елементів.

Приклад 11.9. Створити програму з використанням масиву за умо­вою прикладу 11.8.

// Р11_9.СРР — использование файла "Tmassiv.h"

#include <iostream.h>

#include <conio.h>

#include "Tmassiv.h" // подключение файла "Tmassiv.h"

main() {

Tmassiv mas(5);         /* используется класс Tmassiv, описанный в файле "Tmassiv.h" */

int і;

float m;

for (і = 0; і < mas.fsize(); i++)

{ cout << "Enter "<< і << " element\n";

cin >> m;

mas.vvod(m,i);

}

cout << "Enter prizn.\n";

cin >> mas.pr;

mas.sort();

for (i = 0; і < mas.fsize(); i++)

cout << "mas[" << і << "]=" << mas.vivod(i) << " ";

сout << endl;

getch (); 

return 0;

}

Результати роботи програми:

Enter 0 element 5.2

Enter 1 element 4.8

Enter 2 element 10

Enter 3 element 0.5

Enter 4 element 4.8

Enter prizn. 1

mas[0]=10    mas[l]=5.2   mas[2]=4.9    mas[3]=4.8    mas[4J=0.5

Enter prizn. 2

mas[0]=0.5    mas[l]=4.8    mas[2]=4.9    mas[3]=5.2    mas[4]=10

Слід зауважити, що оголошення класу не залежить від голов­ної програми. Створений у класі масив можна використовувати в ній по-різному, залежно від необхідності (визначати суму його елементів тощо). Але для цього краще використовувати функції члени класу.

Для розміщення елементів масиву використовується дина­мічна пам’ять, що виділяється в конструкторі за допомогою опе­ратора new:

ptr = new float [sz];,

а звільняється деструктором за допомогою оператора delete:

delete[ ] ptr;.

Тому для обробки масивів використання конструкторів і де­структорів є обов’язковим.

Розглянемо, як треба обробляти матрицю, яка являє собою масив масивів. Її ім’я — це покажчик на масив покажчиків, кожен з яких є покажчиком на рядок матриці, тобто на зви­чайний масив.

В оголошенні динамічної матриці з ім’ям рт треба викорис­товувати запис — **рm(форма pm[n][m] є помилковою) і виді­ляти динамічну пам’ять як для покажчика на масив покажчи­ків m, так і для кожного покажчика на рядок рm.

Приклад 11.10. Ввести матрицю та обчислити суми елементів, які розташовано вище і нижче елементів головної діагоналі.

// Р11_10.СРР — вычисление необходимых сумм элементов матрицы

#include <iostream.h>

#include <conio.h>

class Tmatr {

int n, m;

public:

int **pm;

Tmatr(int a, int b);

~Tmatr();

void vvod();

int sum1();

int sum2();

};

Tmatr::Tmatr(int a, int b)           //---------- конструктор класса

// выделение динамич. памяти для матрицы из а строк и b столбцов

{

n = a; m = b; pm = new int *[m];

for (int і = 0; і < n; і++)

pm[i] = new int[m];

}

Tmatr:: ~Tmatr()     //---------------- деструктор класса

// освобождение памяти

{

for (int і = о; і < n; i++)

delete [ ] pm[i];

delete[ ] pm;

}

void Tmatr::vvod() // функция ввода матрицы

{

for (int і = 0; і < n; i++)

{ cout << "\nEnter elementi " << і << " stroki\n";

for (int j = 0; j < m; j++)

cin >> pm[i][j];

}

}

int Tmatr::sum1()     /* функция подсчета суммы элементов, расположенных ниже главной диагонали матрицы */

{

int s1 = 0;

for (int і = 0; і < n; і++)

for (int j = 0; j < m; j++)

if (i>j) s1 += pm[i][j];

return s1;

}

int Tmatr::sum2()    /* функция подсчета суммы элементов, расположенных выше главной диагонали матрицы */

{

int і, j, s2 = 0;

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

for (j = 0; j < m; j++)

if(i<j) s2 += pm[i][j];

return s2; }

main() {

Tmatr matr(4,4);

int k;

matr.vvod();

cout«"\ns1 ="<<matr.sum1()<<" s2 = "<<matr.sum2()<<endl;

getch (); 

}

Результати розв’язання програми:

Enter elementi 0 stroki

5 6 7 2

Enter elementi 1 stroki

3 1 4 0

Enter elementi 2 stroki

9 10 11 7

Enter elementi 3 stroki

3 5 5 8

S1 = 36

S2 = 26

У цій програмі створено клас Tmatr, що крім змінних, кон­структора і деструктора містить функції-члени:

  • vvod() — для введення елементів матриці;
  • sum1() — для визначення суми елементів, розташованих нижче головної діагоналі;
  • sum2() — для визначення суми елементів, розташованих вище головної діагоналі матриці.

У головній функції main() оголошено об’єкт matr(4,4) і здійс­нюються звернення до інших функцій програми. Це приводить до одержання значень вказаних сум.

У наступному прикладі розглянемо, як можна записувати до файла дані типу структура, користуючись класом.

Приклад 11.11. Записати дані типу структура у файл та вивести список робітників за заданим фахом.

/* Р11_11.СРР — запись данных типа структура в файл и их обработка */

#include <iostream.h>

#include <string.h>

#include <conio.h>

#include <fstream.h>

#include <stdio.h>

const n=4;

struct rab {

char fam[20];

char spec[30];

float zarpl; };

class Trab {

public: rab spis;

void vvod() /* функция ввода данных типа структура и записи их в файл */

{

int і;

ofstream fout("rab_spis.dat");

if (!fout) cout<<"Cannot open file\n";

for (і = 0; і < n; i++)

{ cont << "Enter " << (i+1) << " fam, spec, zarpl\n";

gets(spis.fam);

gets(spis.spec);

cin >> spis.zarpl;

cout << endl;

fout.write((char*) & spis, sizeof(spis));

}

fout.close();

}

void vivod() /* функция чтения данных типа структура из файла и вывода их на экран*/

{

char fp[30]; int і;

ifstream fin("rab_spis.dat");

if (!fin)

cout << "Cannot open file for reading\n";

cout << "Enter specialiti\n";

gets(fp);

while (fin.read((char*) &spis, sizeof(spis)))

if (strcmp(fp,spis.spec)==0)

cout << spis.fam << " "<< spis.spec <<" "<< spis.zarpl << endl;

}

};

main() {

Trab st; 

cout << "\nWorking program\n";

st.wod();

st.vivod();

getch (); 

}

Результати виконання програми:

Working program

Enter і fam, spec, zarpl

Геращенко И. С.

инженер 950

  Enter 2 fam, spec, zarpl

  Даниленко Т. К.

  слесарь

  650

  Enter 3 fam, spec, zarpl

  Ящук П. H.

  повар

  450

  Enter 5 fam, spec, zarpl

  Яковченко С. С.

  слесарь

  700

  Enter specialiti

  слесарь

  Даниленко Т. К. слесарь 650

  Яковченко С. С. слесарь 700

       У прикладі 11.11 створено клас Trab, що містить дві функ­ції: одна з ім’ям vvod()— призначена для запису в файл ві­домостей про робітників, тобто їх прізвищ (fam),спеціальнос­тей (spec) і розміру платні (zarpl), оформлених у вигляді струк­тури (rab), друга з ім’ям vivod() — для виведення на екран даних робітників заданої спеціальності. На запитання «Enter specialiti» було введено слово «слесарь». Програма виводить дані про всіх слюсарів, які були записані у списку. В головній функції main() оголошено об’єкт класу st і здійснено звернення до його функцій.

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *