Короткі теоретичні відомості. Клас - фундаментальне поняття С++, він лежить в основі багатьох властивостей С++

Клас.

Клас - фундаментальне поняття С++, він лежить в основі багатьох властивостей С++. Клас надає механізм для створення|створіння| об'єктів. У класі відбиті найважливіші концепції об'єктно-орієнтованого програмування: інкапсуляція, спадкоємство, поліморфізм.

З погляду синтаксису, клас в С++ - це структурований тип, утворений на основі вже існуючих типів.

У цьому сенсі|змісті,рації| клас є|з'являється,являється| розширенням поняття структури. У простому випадку клас можна визначити за допомогою конструкції:

тип_класса ім’я_класу{ список_членів_класу};

де тип_класу одне з службових слів class, struct, union;

ім’я_класу – ідентифікатор;

список_членів_класу – визначення і описи даних, що типізуються, і функцій, що належать класу.

Функції – це методи класу, що визначають операції над об'єктом.

Дані – це поля об'єкту, що утворюють його структуру. Значення полів визначає стан об'єкту.

Приклади|зразки|.

struct date // дата

{int month,day,year; // поля: місяць, день, рік

void set(int,int,int); // метод – встановити дату

void get(int*,int*,int*); // метод – одержати|отримати| дату

void next(); // метод – встановити наступну|таку| дату

void print(); // метод – вивести дату

};

struct class complex // комплексне число

{double re,im;

double real(){return(re);}

double imag(){return(im);}

void set(double x,double у|в,біля|){re = x; im = у|в,біля|;}

void print(){cout<<“re = “<<re; cout<<“im = “<<im;}

};

Для опису об'єкту класу (екземпляра|примірника| класу) використовується конструкція

ім’я_класу ім’я_об’єкту;

date today,my_birthday;

date *point = &today; // покажчик на об'єкт типу date

date clim[30]; // масив об'єктів

date &name = my_birthday; // посилання|заслання| на об'єкт

В об'єкти, що визначаються, входять дані, відповідні членам - даним класу. Функції - члени класу дозволяють обробляти дані конкретних об'єктів класу. Звертатися|обертатися| до даних об'єкту і викликати|спричиняти| функції для об'єкту можна двома способами. Перший за допомогою “кваліфікованих” імен:

ім’я_об’єкту ім’я_даного

ім’я_объекту ім’я_ функції

Приклад:

complex x1,x2;

x1.re = 1.24;

x1.im = 2.3;

x2.set(5.1,1.7);

x1.print();

Другий спосіб доступу використовує покажчик на об'єкт

покажчик_ на об'єкт –>ім’я_компонента

complex *point = &x1; // або point = new complex;

point –>re = 1.24;

point –>im = 2.3;

point –>print();

Доступність компонентів класу.

У розглянутих|розгледіти| раніше прикладах|зразках| класів компоненти класів є|з'являються,являються| загальнодоступними. У будь-якому місці програми, де “видно|показно|” визначення класу, можна дістати доступ до компонентів об'єкту класу. Тим самим не виконується основний принцип абстракції даних – інкапсуляція (приховування|приховання|) даних усередині об'єкту. Для зміни видимості компонент у визначенні класу можна використовувати специфікатори доступу: public, private, protected.

Загальнодоступні (public) компоненти доступні в будь-якій частині|частці| програми. Вони можуть використовуватися будь-якою функцією як усередині даного класу, так і поза|зовні| ним. Доступ ззовні здійснюється через ім'я об'єкту:

ім’я_об’єкту. ім’я_члена_класу

посилання_на_об’єкт. ім’я_члена_класу

покажчик_на_об’єкт. ім’я_члена_класу

Приватні (private) компоненти локалізовані в класі і не доступні ззовні. Вони можуть використовуватися функціями – членами даного класу і функціями – “друзями” того класу, в якому вони описані.

Захищені (protected) компоненти доступні усередині класу і в похідних класах - нащадках.

Змінити|поміняти| статус доступу до компонентів класу можна і за допомогою використання у визначенні класу ключового|джерельного| слова class. В цьому випадку всі компоненти класу за умовчанням є|з'являються,являються| приватними

Приклад|зразок|.

class complex

{

double re, im; // private за умовчанням

public:

double real(){return re;}

double imag(){return im;}

void set(double x,double у|в,біля|){re = x; im = у|в,біля|;}

};

Конструктор.

Недоліком|нестачею| розглянутих|розгледіти| раніше класів є|з'являється,являється| відсутність автоматичної ініціалізації створюваних об'єктів. Для кожного новостворюваного об'єкту необхідно було викликати|спричинити| функцію типу set (як для класу complex) або явно присвоювати значення даним об'єкту. Проте|однак| для ініціалізації об'єктів класу в його визначення можна явно включити спеціальну компонентну функцію, звану конструктором. Формат визначення конструктора наступний|слідуючий|:

ім'я _класу(список_форм_параметрів){ оператори_тіла_конструктора}

Ім'я цієї компонентної функції за правилами мови|язика| С++ повинне співпадати|збігатися| з|із| ім'ям класу. Така функція автоматично викликається|спричиняється| при визначенні або розміщенні в пам'яті за допомогою оператора new кожного об'єкту класу.

Приклад|зразок|.

сomplex(double re1 = 0.0,double im1 = 0.0){re = re1; im = im1;}

Конструктор виділяє пам'ять для об'єкту і ініціалізує дані - члени класу.

Конструктор має ряд|лаву,низку| особливостей:

* Для конструктора не визначається тип значення, що повертається. Навіть тип void не припустимий.

* Покажчик на конструктор не може бути визначений, і відповідно не можна одержати|отримати| адресу конструктора.

* Конструктори не успадковуються|наслідують|.

* Конструктори не можуть бути описані з|із| ключовими|джерельними| словами virtual, static, const, mutuable, valatile.

Конструктор завжди існує для будь-якого класу, причому, якщо він не визначений явно, він створюється автоматично. За умовчанням створюється конструктор без параметрів і конструктор копіювання. Якщо конструктор описаний явно, то конструктор за умовчанням не створюється. За умовчанням конструктори створюються загальнодоступними (public).

Параметром конструктора не може бути його власний клас, але|та| може бути посилання|заслання| на нього (T&). Без явної вказівки програміста конструктор завжди автоматично викликається|спричиняється| при визначенні (створенні|створінні|) об'єкту. В цьому випадку викликається|спричиняється| конструктор без параметрів. Для явного виклику конструктора використовуються дві форми:

ім'я _класу ім'я _об’єкту (фактичні_параметри);

ім'я _класу (фактичні_параметри);

Перша форма допускається тільки|лише| при не порожньому|пустому| списку фактичних параметрів. Вона передбачає виклик конструктора при визначенні нового об'єкту даного класу:

complex ss (5.9,0.15);

Друга форма виклику приводить|призводить,наводить| до створення|створіння| об'єкту без імені:

complex ss = complex (5.9,0.15);

Існують два способи ініціалізації даних об'єкту за допомогою конструктора. Раніше ми розглядали|розглядували| перший спосіб, а саме передачу значень параметрів в тіло конструктора. Другий спосіб передбачає застосування|вживання| списку ініціалізаторів даного класу. Цей список розміщується| між списком параметрів і тілом конструктора. Кожен ініціалізатор| списку відноситься до конкретного компоненту і має вигляд|вид|:

ім’я_даного (вираз|вираження|)

Приклади|зразки|.

class CLASS_A

{

int i; float e; char з|із|;

public:

CLASS_A(int ii,float ее,char cc) : i(8),e( i * її + ii ),с(сс|){

. . .

};

Клас “символьний рядок”.

#include <string.h>

#include <iostream.h>

class string

{

char *ch; // покажчик на текстовий рядок

int len; // довжина текстового рядка

public:

// конструктори

// створює об'єкт – порожній|пустий| рядок

string(int N = 80): len(0){ch = new char[N+1]; ch[0]= ‘0’;}

// створює об'єкт по заданому рядку

string(const char *arch){len = strlen(arch);

ch = new char[len+1];

strcpy(ch,arch);}

// компоненти-функції

// повертає посилання|заслання| на довжину рядка

int& len_str(void){return len;}

// повертає покажчик на рядок

char *str(void){return ch;}

. . .};

Тут в|в,біля| класі string два конструктори – перенавантажувані|перевантажувані| функції.

За умовчанням створюється також конструктор копіювання вигляду|виду|

T::T(const T&),

де Т – ім'я класу. Конструктор копіювання викликається|спричиняється| всякий|усякий| раз, коли виконується копіювання об'єктів, що належать класу. Зокрема він викликається|спричиняється|:

а) коли об'єкт передається функції по значенню;

б) при побудові|шикуванні| тимчасового об'єкту який повертає функція;

в) при використанні об'єкту для ініціалізації іншого об'єкту.

Якщо клас не містить|утримує| явним чином певного конструктора копіювання, то при виникненні одній з цих трьох ситуацій проводиться|виробляється,справляється| побітове копіювання об'єкту. Побітове копіювання не у всіх випадках є|з'являється,являється| адекватним. Саме для таких випадків і необхідно визначити власний конструктор копіювання. Наприклад, в класі string:

string(const string& st)

{len=strlen(st.len);

ch=new char[len+1];

strcpy(ch,st.ch); }

Можна створювати масив об'єктів, проте|однак| при цьому відповідний клас повинен мати конструктор за умовчанням (без параметрів).

Масив об'єктів може ініціалізуватися або автоматично конструктором за умовчанням, або явним привласненням значень кожному елементу масиву.

class demo{

int x;

public:

demo(){x=0;}

demo(int i){x=i;}

};

void main(){

class demo а[20]; //виклик конструктора без параметрів(за умовчанням)

class demo b[2]={demo(10),demo(100)};//явне привласнення

Деструктори.

Динамічне виділення пам'яті для об'єкту створює необхідність звільнення|визволення| цієї пам'яті при знищенні об'єкту. Наприклад, якщо об'єкт формується як локальний усередині блоку, то доцільно, щоб при виході з|із| блоку, коли вже об'єкт перестає існувати, виділена для нього пам'ять була повернена. Бажано, щоб звільнення|визволення| пам'яті відбувалося|походило| автоматично. Таку можливість|спроможність| забезпечує спеціальний компонент класу – деструктор класу. Його формат:

~ім’я_класу(){ оператори_тіла_деструктора}

Ім'я деструктора співпадає|збігається| з|із| ім'ям його класу, але|та| передує символом “~” (тильда).

Деструктор не має параметрів і не повертає ніякого значення. Виклик

деструктора виконується неявно (автоматично), як тільки об'єкт класу знищується.

Наприклад, при виході за область визначення або при виклику оператора delete для покажчика на об'єкт:

string *p=new string (“рядок”);

delete p;

Якщо в класі деструктор не визначено явно, то компілятор генерує деструктор за умовчанням, який просто звільняє|визволяє| пам'ять, зайняту|позичену,посісти| даними об'єкту. У тих випадках, коли потрібно виконати звільнення|визволення| і інших об'єктів пам'яті, наприклад область, на яку указує|вказує| ch в об'єкті string, необхідно визначити деструктор явно: ~string(){delete []ch;}

Так само, як і для конструктора, не може бути визначений покажчик на деструктор.