Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Sizeof value 6 страница




int getQp(); // Виведення з черги значення

};

 

// Ініціалізація класу chergaClass.

void chergaClass::init()

{

rloc = sloc = 0;

}

 

// Введення в чергу значення.

void chergaClass::putQp(int izm)

{

if (sloc == 100) {

cout << "Черга заповнена.\n";

return;

}

sloc++;

qpMas[sloc] = izm;

}

 

// Виведення з черги значення.

int chergaClass::getQp()

{

if (rloc == sloc) {

cout << "Черга порожня.\n";

return 0;

}

rloc++;

return qpMas[rloc];

}

 

int main ()

{

chergaClass A_ob, B_ob; // Створення двох об'єктів класу.

 

A_ob.init();

B_ob.init();

 

A_ob.putQp(10);

B_ob.putQp(19);

 

A_ob.putQp(20);

B_ob.putQp(1);

 

cout << "Вміст черги A_ob: ";

cout << A_ob.getQp() << " ";

cout << A_ob.getQp() << "\n";

 

cout << "Вміст черги B_ob: ";

cout << B_ob.getQp() << " ";

cout << B_ob.getQp() << "\n";

 

getch (); return 0;

}

У процесі виконання ця програма відображає на екрані такі результати:

Вміст черги A_ob: 10 20

Вміст черги B_ob: 19 1

Необхідно пам'ятати! Закриті члени класу доступні тільки функціям, які є членами цього класу.

Наприклад, таку настанову

A_ob.rloc = 0;

не можна включити у функцію main () нашої програми.

12.2. Конструктори і деструктори

Як правило, певну частину об'єкта, перш ніж його можна буде використовувати, необхідно ініціалізувати. Наприклад, розглянемо клас chergaClass, який було представлено вище у цьому підрозділі. Перш ніж об'єкти класу chergaClass можна буде використовувати, змінним rloc і sloc потрібно надати нульові значення. У нашому випадку ця вимога виконувалася за допомогою функції init(). Але, оскільки вимога ініціалізації членів-даних класу є достатньо поширеною, у мові програмування C++ передбачено реалізацію цієї потреби під час створення об'єктів класу. Така автоматична ініціалізація членів-даних класу виконується завдяки використанню конструктора.

Конструктор – це спеціальна функція, яка є членом класу, а її ім'я обов'язково збігається з іменем класу. Ось, наприклад, як може виглядати клас chergaClass після його перероблення, пов'язаного із застосуванням конструктора для ініціалізації його членів-даних класу:

class chergaClass { // Оголошення класового типу

int qpMas[100];

int sloc, rloc;

public:

chergaClass(); // Оголошення конструктора

void putQp(int izm); // Введення в чергу значення

int getQp(); // Виведення з черги значення

};

Звернемо Вашу увагу на те, що в оголошенні конструктора chergaClass() відсутній тип значення, що повертається. У мові програмування C++ конструктори не повертають значень і, як наслідок, немає сенсу вказувати їх тип[45].

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

Тепер наведемо код функції chergaClass():

// Визначення конструктора

chergaClass::chergaClass()

{

sloc = rloc = 0;

cout << "Чергу ініціалізовано.\n";

}

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

Конструктор об'єкта викликається під час створення об'єкта. Це означає, що він викликається у процесі виконання настанови створення об'єкта. Конструктори глобальних об'єктів викликаються на самому початку виконання програми, тобто ще до звернення до функції main (). Що стосується локальних об'єктів, то їх конструктори викликаються кожного разу, коли трапляється потреба створення такого об'єкта.

Доповненням до конструктора слугує деструктор. У багатьох випадках під час руйнування об'єкта необхідно виконати певну дію або навіть певні послідовності дій. Локальні об'єкти створюються під час входу в блок, у якому вони визначені, і руйнуються при виході з нього. Глобальні об'єкти руйнуються при завершенні програми. Існує багато чинників, що зумовлюють необхідність використання деструкторів. Наприклад, об'єкт повинен звільнити раніше виділену для нього пам'ять. У мові програмування C++ саме деструкторам доручається оброблення процесу деактивізації об'єкта.

Ім'я деструктора має збігатися з іменем конструктора, але йому передує символ "~". Подібно до конструкторів, деструктори не повертають значень, а отже, в їх оголошеннях відсутній тип значення, що повертається.

Деструктор – це функція, яка викликається під час руйнування об'єкта.

Розглянемо вже знайомий нам клас chergaClass, але тепер він має містити конструктор і деструктор[46]:

class chergaClass { // Оголошення класового типу

int qpMas[100];

int sloc, rloc;

public:

chergaClass(); // Оголошення конструктора

~chergaClass(); // Оголошення деструктора

void putQp(int izm); // Введення в чергу значення

int getQp(); // Виведення з черги значення

};

 

// Визначення конструктора.

chergaClass::chergaClass()

{

sloc = rloc = 0;

cout << "Чергу ініціалізовано.\n";

}

 

// Визначення деструктора.

chergaClass::~chergaClass()

{

cout << "Чергу зруйновано.\n";

}

Ось як виглядатиме нова версія коду програми реалізації черги, у якій продемонстровано механізм використання конструктора і деструктора.

Код програми 12.2. Демонстрація механізму використання конструктора і деструктора

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

class chergaClass { // Оголошення класового типу

int qpMas[100];

int sloc, rloc;

public:

chergaClass(); // Оголошення конструктора

~chergaClass(); // Оголошення деструктора

void putQp(int izm); // Введення в чергу значення

int getQp(); // Виведення з черги значення

};

 

// Визначення конструктора.

chergaClass::chergaClass()

{

sloc = rloc = 0;

cout << "Чергу ініціалізовано.\n";

}

 

// Визначення деструктора.

chergaClass::~chergaClass()

{

cout << "Чергу зруйновано.\n";

}

 

// Введення в чергу значення.

void chergaClass::putQp(int izm)

{

if (sloc == 100) {

cout << "Черга заповнена.\n";

return;

}

sloc++;

qpMas[sloc] = izm;

}

 

// Виведення з черги значення.

int chergaClass::getQp()

{

if (rloc == sloc) {

cout << "Черга порожня.\n";

return 0;

}

rloc++;

return qpMas[rloc];

}

 

int main ()

{

chergaClass A_ob, B_ob; // Створення двох об'єктів класу.

 

A_ob.putQp(10);

B_ob.putQp(19);

 

A_ob.putQp(20);

B_ob.putQp(1);

 

cout << A_ob.getQp() << " " << A_ob.getQp() << "\n";

cout << B_ob.getQp() << " " << B_ob.getQp() << "\n";

 

getch (); return 0;

}

У процесі виконання ця програма виводить на екран такі результати:

Чергу ініціалізовано.

Чергу ініціалізовано.

10 20

19 1

Чергу зруйновано.

Чергу зруйновано.

12.2.1. Параметризовані конструктори

Конструктор може мати параметри. За допомогою них під час створення об'єкта членам-даних (змінним класу) можна подати деякі початкові значення, що визначаються у основній функції main (). Це реалізується шляхом передачі аргументів конструктору об'єкта. У наведеному нижче прикладі спробуємо удосконалити клас chergaClass так, щоб він приймав аргументи, які слугуватимуть ідентифікаційними номерами (nom) черги. Передусім необхідно внести зміни у визначення класу chergaClass:

class chergaClass { // Оголошення класового типу

int qpMas[100];

int sloc, rloc;

int who; // Містить ідентифікаційний номер черги

public:

chergaClass(int nom); // Оголошення параметризованого конструктора

~chergaClass(); // Оголошення деструктора

void putQp(int izm); // Введення в чергу значення

int getQp(); // Виведення з черги значення

};

Член-даних who використовують для зберігання ідентифікаційного номера (nom), створюваного програмою черги. Її реальне значення визначається значенням, що передається конструктору як формальний параметр nom, під час створення змінної типу chergaClass. Конструктор chergaClass() буде мати такий вигляд:

// Визначення параметризованого конструктора

chergaClass::chergaClass(int nom)

{

sloc = rloc = 0;

who = nom;

cout << "Чергу " << who << " ініціалізовано.\n";

}

Щоб передати аргумент конструкторові, необхідно пов'язати цей аргумент з об'єктом під час його створення. Мова програмування C++ підтримує два способи реалізації такого зв'язування:

Варіант 1 Варіант 2 (альтернативний)

chergaClass A_ob = chergaClass(101); chergaClass A_ob = 101;

У цьому оголошенні створюється черга з іменем A_ob, якій передається значення (ідентифікаційний номер) 101. Але цей формат (у такому контексті) використовується рідко, оскільки другий спосіб має коротший запис і тому зручніший для використання. У другому способі аргумент повинен знаходитися за іменем об'єкта і поміщатися в круглі дужки. Наприклад, така настанова еквівалентна попереднім визначенням:

chergaClass A_ob(101);

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

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

У цьому записі елемент список_аргументів є переліком аргументів, розділених між собою комами, що передаються конструктору.

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

У наведеному нижче коді програми реалізації черги продемонстровано механізм використання параметризованого конструктора.

Код програми 12.3. Демонстрація механізму використання параметризованого конструктора

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

class chergaClass { // Оголошення класового типу

int qpMas[100];

int sloc, rloc;

int who; // Містить ідентифікаційний номер черги

public:

chergaClass(int nom); // Оголошення параметризованого конструктора

~chergaClass(); // Оголошення деструктора

void putQp(int izm); // Введення в чергу значення

int getQp(); // Виведення з черги значення

};

 

// Визначення параметризованого конструктора.

chergaClass::chergaClass(int nom)

{

sloc = rloc = 0;

who = nom;

cout << "Чергу " << who << " ініціалізовано.\n";

}

 

// Визначення деструктора.

chergaClass::~chergaClass()

{

cout << "Чергу " << who << " зруйновано.\n";

}

 

// Введення в чергу значення.

void chergaClass::putQp(int izm)

{

if (sloc == 100) {

cout << "Черга заповнена.\n";

return;

}

sloc++;

qpMas[sloc] = izm;

}

 

// Виведення з черги значення.

int chergaClass::getQp()

{

if (rloc == sloc) {

cout << "Черга порожня.\n";

return 0;

}

rloc++;

return qpMas[rloc];

}

 

int main ()

{

// Створення та ініціалізація двох об'єктів.

chergaClass A_ob(1), B_ob(2);

 

A_ob.putQp(10);

B_ob.putQp(19);

 

A_ob.putQp(20);

B_ob.putQp(1);

 

cout << A_ob.getQp() << " " << A_ob.getQp() << "\n";

cout << B_ob.getQp() << " " << B_ob.getQp() << "\n";

 

getch (); return 0;

}

У процесі виконання У процесі виконання ця програма відображає на екрані такі результати:

Чергу 1 ініціалізовано.

Чергу 2 ініціалізовано.

10 20

19 1

Чергу 2 зруйновано.

Чергу 1 зруйновано.

Як видно з коду функції main (), черзі, пов'язаній з іменем A_ob, присвоюється ідентифікаційний номер 1, а черзі з іменем B_ob – ідентифікаційний номер 2.

Хоча у прикладі з використанням класу chergaClass під час створення об'єкта передається тільки один аргумент, у загальному випадку можлива передача двох і більше аргументів. У наведеному нижче прикладі об'єктам типу widClass передається два параметри.

Код програми 12.4. Демонстрація механізму передачі конструктору двох параметрів

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

class widClass { // Оголошення класового типу

int izm, jzm;

public:

widClass(int a, int b); // Оголошення параметризованого конструктора

void putWid();

};

 

// Передаємо 2 аргументи конструктору widClass().

widClass::widClass(int a, int b)

{

izm = a; jzm = b;

cout << "Чергу ініціалізовано.\n";

}

 

void widClass::putWid()

{

cout << "izm= " << izm << "; jzm= " << jzm << "\n";

}

 

int main ()

{

// Створення та ініціалізація двох об'єктів.

widClass X_ob(10, 20), Y_ob(0, 0);

 

X_ob.putWid();

Y_ob.putWid();

 

getch (); return 0;

}

У процесі виконання ця програма відображає на екрані такі результати:

Чергу ініціалізовано.

Чергу ініціалізовано.

izm= 10; jzm= 20

izm= 0; jzm= 0

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

12.2.2. Альтернативний варіант ініціалізації членів-даних об'єкта

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

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

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

class myClass { // Оголошення класового типу

int a;

public:

myClass(int x); // Оголошення параметризованого конструктора

int getAzm();

};

 

myClass::myClass(int x)

{

a = x;

cout << "Чергу ініціалізовано.\n";

}

int myClass::getAzm()

{

return a;

}

 

int main ()

{

myClass M_ob = 4; // Створення об'єкта M_ob та надання йому

// числового значення

cout << M_ob.getAzm() << "\n";

getch (); return 0;

}

У цій програмі конструктор для об'єктів класу myClass приймає тільки один параметр. Звернемо Вашу увагу на те, як у функції main () визначається об'єкт M_ob. Для цього використовують такий формат визначення:

myClass M_ob = 4;

У цьому форматі ініціалізації членів-даних об'єкта число 4 автоматично передається параметру х під час виклику конструктора myClass(). Іншими словами, ця настанова визначення обробляється компілятором так, якби вона була записана так:

myClass M_ob = myClass(4);

У загальному випадку, якщо у Вас є конструктор, який приймає тільки один аргумент, то для ініціалізації членів-даних об'єкта Ви можете використовувати або варіант M_ob(x), або варіант M_ob = х. Йдеться про те, що під час створення конструктора з одним аргументом опосередковано створюється перетворення з типу цього аргументу в тип цього класу.

Необхідно пам'ятати! Показаний вище альтернативний спосіб ініціалізації членів-даних об'єктів застосовується тільки до конструкторів, які мають тільки один параметр.

12.3. Доступ до членів класу

Засвоєння механізму доступу до членів класу – ось що часто бентежить програмістів-початківців. Тому зупинимося на цій темі детальніше. Насамперед розглянемо таку просту програму, в якій демонструється отримання доступу до членів класу.

Код програми 12.6. Демонстрація отримання доступу до членів класу

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

class myClass { // Оголошення класового типу

int a; // Закритий член-даних

public:

int b; // Відкритий член-даних

void setAzm(int izm); // Відкриті функції-члени класу

int getAzm();

void reset();

};

 

void myClass::setAzm(int izm) // Надання значень членам-даних

{

a = izm; // Пряме звернення до змінної а

b = izm*izm; // Пряме звернення до змінної b

}

int myClass::getAzm() // Повернення значення закритого члена даних

{

return a; // Пряме звернення до змінної а

}

void myClass::reset() // Надання значень членам-даних

{

// Прямий виклик функції setAzm() створеним об'єктом

setAzm(0);

}

 

int main ()

{

myClass M_ob; // Створення об'єкта класу

 

M_ob.setAzm(5); // Надання значень членам-даних

cout << "Об'єкт M_ob після виклику функції setAzm(5): ";

cout << M_ob.getAzm() << " ";

cout << M_ob.b << "\n"; // До члена b можна отримати прямий доступ,

// оскільки він є public-членом.

 

M_ob.b = 20; // Члену b можна надати значення безпосередньо,

// оскільки він є public-членом.

cout << "Об'єкт M_ob після встановлення члена M_ob.b=20: ";

cout << M_ob.getAzm() << " " << M_ob.b << "\n";

 

M_ob.reset();

cout << "Об'єкт M_ob після виклику функції M_ob.reset(): ";

cout << M_ob.getAzm() << " " << M_ob.b << "\n";

 

getch (); return 0;

}

У процесі виконання ця програма відображає на екрані такі результати:

Об'єкт M_ob після виклику функції setAzm(5): 5 25

Об'єкт M_ob після встановлення члена M_ob.b=20: 5 20

Об'єкт M_ob після виклику функції M_ob.reset(): 0 0

Тепер розглянемо, як здійснюється доступ до членів класу myClass. Передусім звернемо Вашу увагу на те, що для присвоєння значень змінним а і b у функції setAzm() використовуються такі рядки коду програми:

a = izm; // Пряме звернення до змінної а

b = izm*izm; // Пряме звернення до змінної b

Оскільки функція setAzm() є членом класу, то вона може безпосередньо звертатися до членів-даних а і b цього ж класу без вказання імені об'єкта (і не використовуючи при цьому оператора "крапка"). Як ми вже зазначали вище, функція-член класу завжди викликається для певного об'єкта (а коли ж виклик відбувся, то об'єкт, як наслідок, є відомим). Таким чином, у тілі функції-члена класу немає потреби вказувати об'єкт повторно. Отже, посилання на змінні а і b застосовуватимуться до копій цих змінних, що належать об'єкту, який їх викликає.

Тепер звернемо Вашу увагу на те, що змінна b – відкритий (public) член даних класу myClass. Це означає, що до змінної b можна отримати доступ з коду програми, визначеного поза тілом класу myClass. Наведений нижче рядок коду програми з функції main (), у процесі виконання якої змінній b присвоюється число 20, демонструє реалізацію такого прямого доступу:

M_ob.b = 20; // До члена b можна отримати прямий доступ,

// оскільки він є public -членом.

Оскільки ця настанова не належить тілу класу myClass, то до змінної b можливий доступ тільки з використанням імені конкретного об'єкта (у цьому випадку об'єкта M_ob) і оператора "крапка".

Тепер звернемо Вашу увагу на те, як викликається функція-член класу reset() з основної функції main ():

M_ob.reset();

Оскільки функція reset() є відкритим членом класу, то її також можна викликати з коду програми, визначеного поза тілом класу myClass, і за допомогою імені конкретного об'єкта (у цьому випадку об'єкта M_ob).

Розглянемо детальніше код функції reset(). Той факт, що вона є функцією-членом класу, дає змогу їй безпосередньо звертатися до інших членів того ж самого класу, не використовуючи оператора "крапка" або імені конкретного об'єкта. Вона викликає функцію-члена setAzm(). І знову ж таки, оскільки об'єкт вже відомий (він використовується для виклику функції reset()), то немає ніякої потреби вказувати його ще раз.

Тут важливо зрозуміти таке: коли доступ до деякого члена класу відбувається ззовні цього класу, то його необхідно кваліфікувати (уточнити) за допомогою імені конкретного об'єкта. Але сама функція-член класу може безпосередньо звертатися до інших членів того ж самого класу.

Необхідно пам'ятати! Не варто хвилюватися з приводу того, що Ви ще не відчули в собі упевненості щодо механізму отримання доступу до членів класу. Невелике Ваше занепокоєння під час освоєння цієї теми – звичайне явище для програмістів-початківців. Сміливо продовжуйте читати навчальний посібник, розглядаючи якомога більше прикладів, і тема доступу до членів класу незабаром стане такою ж простою, як таблиця множення для першокласника!

12.4. Класи і структури – споріднені типи

Як згадувалося в попередньому розділі, у мові програмування C++ структура також володіє об'єктно-орієнтованими можливостями. По суті, класи і структури можна назвати "близькими родичами". За одним винятком, вони взаємозамінні, оскільки структура також може містити дані та програмні коди, які маніпулюють цими даними так само, як і це може робити клас. Єдина відмінність між С++-структурою і С++-класом полягає у тому, що за замовчуванням члени класу є закритими, а члени структури – відкритими. У іншому ж структури і класи мають однакове призначення. Насправді відповідно до формального синтаксису мови програмування C++ оголошення структури створює тип класу.

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

Код програми 12.7. Демонстрація механізму використання структури для створення класу

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

struct buildStruct { // Оголошення структурного типу

int getIzm(); // Ці члени відкриті (public)

void putIzm(int jzm); // за замовчуванням.

private:

int izm;

};

 

int buildStruct::getIzm()

{

return izm;

}

 

void buildStruct::putIzm(int jzm)

{

izm = jzm;

}

 

int main ()

{

buildStruct S_ob; // Створення об'єкта структури

 

S_ob.putIzm(10);

cout << "izm= " << S_ob.getIzm() << "\n";

 

getch (); return 0;

}

У цій програмі визначається тип структури з іменем buildStruct, у якій функції-члени getIzm() і putIzm() є відкритими (public), а член даних izm – закритим (private). Звернемо Вашу увагу на те, що у структурах для оголошення закритих членів використовують ключове слово private.

Ключове слово private використовують для оголошення закритих членів класу.




Поделиться с друзьями:


Дата добавления: 2014-11-29; Просмотров: 508; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.21 сек.