Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
8
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

7.1.1. Локальні змінні

Як зазначалося вище, змінні, які оголошено всередині функції, називаються локальними. Але у мові програмування C++ передбачено "уважніше" відношення до локальних змінних, ніж ми могли помітити дотепер. У мові програмування C++ змінні можуть бути включені в блоки. Це означає, що змінну можна оголосити усередині будь-якого блоку коду програми, після чого вона буде локальною стосовно цього блоку1. Насправді змінні, локальні стосовно функції, утворюють просто спеціальний випадок більш загальної ідеї.

Локальну змінну можуть використовувати тільки настанови, включені в блок, у якому ця змінна оголошена. Іншими словами, локальна змінна невідома за межами власного блоку коду програми. Отже, записані поза блоком настанови не можуть отримати доступ до об'єкта, що визначається усередині блоку.

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

Найпоширенішим програмним блоком є функція. У мові програмування C++ кожна функція визначає блок коду програми, який починається з відкритої фігурної дужки цієї функції та завершується її закритою фігурною дужкою. Код функції та її дані – це її "приватна власність", і до неї не може отримати доступ жодна настанова з будь-якої іншої функції, за винятком настанови її виклику2. Тіло функції надійно приховане від решти частини програми і, якщо у функції не використовуються глобальні змінні, то вона не може зробити ніякого впливу на інші частини програми, однаково, як і ті на неї. Таким чином, вміст однієї функції зовсім незалежний від вмісту іншої. Іншими словами, програмні коди і дані, визначені в одній функції, не можуть взаємодіяти з кодами і даними, визначеними в іншій, оскільки дві функції мають різні області видимості.

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

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

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

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

void fun_1();

int main()

{

char strMas[] = "Це масив strMas у функції main().";

cout << strMas << "\n";

fun_1();

cout << strMas << "\n";

getch(); return 0;

}

void fun_1()

{

char strMas[80];

cout << "Введіть будь-який рядок: ";

cin >> strMas;

cout << strMas << "\n";

}

Символьний масив strMas оголошується тут двічі: перший раз у функції main() і ще раз у функції fun_1(). При цьому масив strMas, оголошений у функції main(), не має жодного стосунку до однойменного масиву з функції fun_1(). Як пояснювалося вище, кожен масив (у цьому випадку strMas) відомий тільки блоку коду програми, у якому він оголошений. Щоб переконатися у цьому, достатньо виконати наведену вище програму. Як бачите, хоча масив strMas отримує рядок, що вводиться користувачем у процесі виконання функції fun_1(), вміст масиву strMas у функції main() залишається незмінним.

Мова C++ містить ключове слово auto, яке можна використовувати для оголошення локальних змінних. Але оскільки всі не глобальні змінні є за замовчуванням auto-змінними, то до цього ключового слова практично ніколи не вдаються. Тому Ви не знайдете у цьому навчальному посібнику жодного прикладу з його використанням. Але, якщо Ви захочете все-таки застосувати його у своїй програмі, то знайте, що розміщувати його потрібно безпосередньо перед типом змінної, як це показано нижче:

auto char ch;

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

Щоб краще зрозуміти зазначене вище, розглянемо таку програму:

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

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

#include <cstring> // Для роботи з рядковими типами даних

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

int main()

{

int vybir;

cout << "(1) додати числа або ";

cout << "(2) конкатенувати рядки?: ";

cin >> vybir;

if(vybir == 1) {

int a, b; // Активізуються дві int-змінні.

cout << "Введіть два числа: ";

cin >> а >> b;

cout << "Сума дорівнює " << a + b << "\n";

}

else {

char s1[80], s2[80]; // Активізуються два рядки.

cout << "Введіть два рядки: ";

cin >> s1;

cin >> s2;

strcpy(s1, s2);

cout << "Конкатенація дорівнює " << s1 << "\n";

}

getch(); return 0;

}

Ця програма, залежно від вибору користувача, забезпечує введення двох чисел або двох рядків. Звернемо Вашу увагу на оголошення змінних а і b в if-блоці і змінних s1 і s2 у else-блоці. Існування цих змінних почнеться з моменту входу у відповідний блок і припиниться відразу після виходу з нього. Якщо користувач вибере додавання чисел, будуть створені змінні а і b, а якщо він захоче конкатенувати рядки – то змінні s1 і s2. Нарешті, ні до однієї з цих змінних не можна звернутися ззовні їх блоку, навіть з частини коду програми, що належить тій самій функції. Наприклад, якщо Ви спробуєте скомпілювати наступну (некоректну) версію програми, то отримаєте повідомлення про помилку.

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

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

#include <cstring> // Для роботи з рядковими типами даних

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

int main()

{

int vybir;

cout << "(1) додати числа або ";

cout << "(2) конкатенувати рядки?: ";

cin >> vybir;

if(vybir == 1) {

int a, b; // Активізуються дві int-змінні.

cout << "Введіть два числа: ";

cin >> а >> b;

cout << "Сума дорівнює " << a + b << "\n";

}

else {

char s1[80], s2[80]; /* Активізуються два рядки. */

cout << "Введіть два рядки: ";

cin >> s1;

cin >> s2;

strcpy(s1, s2);

cout << "Конкатенація дорівнює " << s1 << "\n";

}

a = 10; // *** Помилка ***

// Змінна а тут невідома!

getch(); return 0;

}

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

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

Код програми 7.3. Демонстрація перевизначення "зовнішньої" змінної на "внутрішню"

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

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

int main()

{

int izm, jzm;

izm = 10; jzm = 100;

if(jzm > 0) {

int izm; // Ця змінна izm відокремлена від

// зовнішньої змінної izm.

izm = jzm / 2;

cout << "Внутрішня змінна izm: " << izm << "\n";

}

cout << "Зовнішня змінна izm: " << izm << "\n";

getch(); return 0;

}

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

Внутрішня змінна izm: 50

Зовнішня змінна izm: 10

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

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

Локальні змінні не зберігають своїх значень між активізаціями.

Локальні змінні зберігаються в стеку, якщо не задано іншого способу зберігання. Оскільки стек – це динамічно змінна область пам'яті, локальні змінні не можуть в загальному випадку зберігати свої значення між викликами функцій.

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

Код програми 7.4. Демонстрація місця оголошення змінних

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

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

int main()

{

cout << "Введіть число: ";

int a; // Оголошуємо одну змінну.

cin >> а;

cout << "Введіть друге число: ";

int b; // Оголошуємо ще одну змінну.

cin >> b;

cout << "Добуток дорівнює: " << a*b << "\n";

getch(); return 0;

}

У наведеному прикладі змінні а і b не оголошуються доти, доки вони стануть потрібними. Все ж таки більшість програмістів оголошують усі локальні змінні на початку блоку, у якому вони використовуються, але це, як мовиться, питання стилістики (або смаку).