Поняття класу

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

Оголошення класу має таку форму:

class сім’я класу> : список класів-батьків>

{

public:             // доступно всем

<дані, методи, властивості, події>

protected: // доступно только потомкам

<дані, методи, властивості, події>

private:   // доступно только в классе

<дані, методи, властивості, події>

} <список змінних>

Об’єкт — це змінна типу клас. Дані класу називаються по­лями, а функції —методами, що призначені для обробки полів. Крім методів, тип клас може мати спеціальні функції — конструктори і деструктори.

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

Розміщення описів змінних і функції з їх обробки, тобто полів та методів в одному класі називається інкапсуляцією.

Класи в С++ мають три різних рівні доступу до своїх еле­ментів, тобто даних (полів) і функцій (методів):

  • закриті елементи (private);
  • захищені елементи (protected);
  • відкриті елементи (public).

До даних у закритому розділі (private) мають доступ тіль­ки функції-елементи свого класу. Класам-нащадкам забороня­ється доступ до закритих даних своїх базових (батьківських) класів. За замовчуванням усі дані-члени класу мають атрибут private(закритий).

До даних у захищеному розділі (protected) мають доступ функції свого класу і функції класів-нащадків.

У свою чергу до даних відкритого розділу (public) можуть звертатися будь-які функції.

Існують такі правила створення розділів класу:

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

 

Розглянемо приклад використання класу.

Приклад 11.1. Навести просту програму з використанням класу.

// P11_1.CPP — использование класса, структура класса

#include <iostream.h>

#include <conio.h>

class myclass {

int p;                            // закрытая переменная no умолчанию

public:

void set_p(int x);        // прототипы функций-членов класса

int get_p();

};

//------------------------- описание функций-членов класса

void myclass::set_p(int x)

{ p = x; }

int myclass::get_p( )

{ return p;

}

main()

{ myclass ob1, ob2;        // объявление объектов

// вызов функций-членов класса

ob1.set_p(10);

ob2.set_p(30);

cout<<"p1= "<<ob1.get_p()<<" ";

cout<<"p2= "<<ob2.get_p()<<endl;

getch (); 

return 0;

}

Результати обчислень:

p1= 10

p2= 30

У програмі оголошено клас з ім’ям myclass, що має одну закриту змінну р і дві відкриті функції-члени класу set_p() і get_p(). Перша з функцій призначена для ініціювання за­критої змінної р, а друга — для її повернення.

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

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

У головній функції main() спочатку оголошуються два об’єк­ти типу myclass, потім ці об’єкти ініціюються конкретними зна­ченнями змінної р (ob1.set_p(10) та ob2.set_p(30),після цього значення цієї змінної виводяться на екран (cont<<ob1.get_p(); таcout<<ob2.get_p0).

Треба звернути увагу, що елементи класу записуються через крапку після імені об’єкта.

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

Головною метою конструкторів є ініціювання змінних-об’єктів класу та розподілення пам’яті для їх зберігання. Конструк­тор викликається кожного разу при створенні об’єкта даного класу або явно, або автоматично (див. Р11_1.СРР).

Основні правила роботи з конструкторами:

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

Наведемо приклади оголошення конструкторів:

Class cls1 {

int х, у;              // защищенные переменные класса

public:

cls1();                 // конструктор по умолчанию без параметров

cls1 (int xval=0; int yval=0); /* конструктор no умолчанию с параметрами, имеющими значения по умолчанию */

cls1(const clsl &pt);    // конструктор копирования

};

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

Якщо в головній програмі оголошено, наприклад:

main() {

cls1 p1; cls1 p2(10,20); cls1 р3(р2);

}……………………………

то у першому випадку буде виконуватися конструктор за замов­чуванням без параметрів, у другому — конструктор з парамет­рами за замовчуванням, у третьому — конструктор копіювання.

Деструктори необхідні для автоматичного руйнування об’єк­тів класу. їх використання має такі особливості:

  • ім’я деструктора повинно починатися знаком ~ (тильда), за яким записується ім’я класу;
  • для деструктора не вказується тип значення, що повер­тається (як і для конструкторів);
  • клас завжди має тільки один деструктор або не має жод­ного. У такому випадку компілятор сам створює деструктор за замовчуванням;
  • деструктор не може мати параметрів; програма автома­тично викликає деструктор, якщо об’єкт класу виходить за ме­жі області дії і повинен бути знищений.

Приклад 11.2. Навести програму, в якій конструктор використо­вується для ініціювання закритої змінної х, а деструктор — для її руй­нування.

// Р11_2. СРР — использование конструкторов и деструкторов

#include <iostream.h>

class myclass2

Конструктори і деструктори необхідні для роботи з ди­намічними даними. Для виділення динамічної пам’яті користу­ються оператором new у конструкторі, а для її звільнення — оператором delete у деструкторі.

Розглянемо програму, в якій за допомогою конструктора виділяється динамічна пам’ять для рядка символів, ініціюєть­ся закрита змінна len, а деструктор звільняє цю пам’ять після її використання.

Приклад 11.3. Навести програму, в якій треба ввести рядок сим­волів, потім вивести на екран цей рядок і кількість символів у ньому.

/* Р11_З.СРР — использование конструкторов и деструкторов при работе с динамическими данными */

 

#include <iostream.h>

#include <string.h>

#include <conio.h>

class strclass {

char *str;

int len;

public:

strclass(int size)          //—————————- конструктор класса

{

str=new char[size]; //выделение динамич. памяти для строки

len=size;

}

~ strclass( )                   //———————————–деструктор класса

{

delete str;                 // освобождение динамической памяти

}

//——————————— прототипы фукщй ввода и вывода

int input(void);

void output(void);

};

//—————————————— функция ввода строки

int strclass::input(void)

{

сout<<“Enter stroky not large “<<len<<” symbols\n”;

cin.getline(str, len);

return strlen(str);

}

/——————————————- функция вывода строки

void strclass::output(void) {

cout << str << ‘\n’;

}

void main() {

int lenght;

strclass my(100);         // объявление объекта класса

lenght = my.input( );

cout << “Stroka= ” << lenght << ” symbols\n”;

my.output( );

getch ();

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

Enter stroky not large 100 symbols

Существуют правила создания разделов класса

Stroka= 43 symbols

Существуют правила создания разделов класса

 

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

Звичайно у базовому класі описуються найбільш загальні властивості, які придатні для всіх похідних від нього класів. Похідний клас успадковує ці загальні властивості і додає нові, характерні тільки для нього.

Загальна форма оголошення похідного класу має вигляд:

ік : [специфікатор доступу] ім’я базового класу { };,

де ік — ім’я оголошеного класу, а у фігурних дужках запису­ється зміст цього класу.

Приклад 11.4. Розробити програму, що реалізує приклад взаємодії базового (class А) і похідного (class В) класів.

// Р11_4.СРР — взаимодействие базового и производного классов

#include <iostream.h>

#include <conio.h>

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

{

int і; public:

void set_i(int n) { і = n; }

int get_i()

{ return i;        }

};

class B: public A           //----------- производный класс

{

int j; public:

void set_j(int n)

{ j = n; }

int mult()

{ return j*get_i();        }

};

main() {

В ob;

ob.set_i(10);

ob.set_j(4);

cout<<"Rezultat= "<<ob.mult()<<endl;

getch (); 
return 0;

}

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

Rezultat= 40

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

У головній програмі оголошено об’єкт ob класу В, однак для його обробки реалізується як функція ob.set_i(10) класу А, так і функція ob.set_j(4) класу В. Тому при виконанні функції ob.mult() буде виведено 40. Якби клас А успадковувався у за­критому (private)режимі, то усі його елементи було б заборо­нено використовувати в класі-нащадку.

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

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