Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс лекцій.doc
Скачиваний:
15
Добавлен:
03.11.2018
Размер:
1.12 Mб
Скачать

5 Глобальні та локальні об’єкти.

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

Глобальні об’єкти.

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

Локальні об’єкти .

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

class empty{

char *obj_name;

empty(char*name)

public:

{cout<<“створений об’єкт з ім’ям”<<name<<“класу empty\n”;

obj_name=name;}

~empty()

{ cout<<“об’єкт з ім’ям”<<obj_name<<“знищений\n”;}

} one(“one”);

void main(void)

{empty second(“second”);}

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

створений об’єкт з ім’ям one класу empty

створений об’єкт з ім’ям second класу empty

об’єкт з ім’ям second знищений

об’єкт з ім’ям one знищений

Вказівники на об’єкти

Вказівники можуть посилатись на динамічні об’єкти , пам’ять для яких виділяється за допомогою операції new:

Ttime *ptoday;

ptoday=new Ttime;

В кучі виділяється область для об’єкту типу Ttime. Адреса першого байту цієї області присвоюється ptoday. Крім того, С++ викликає конструктор по замовчуванню, який ініціалізує об’єкт. Якщо необхідно виділити пам’ять та викликати інший конструктор, необхідно вказати відповідні параметри:

ptoday=new Ttime(9,14,1917,10,45).

Об’єкти-посилання

Об’єкти можуть оголошуватись як посилання. Нехай, наприклад, оголошений такий глобальний об’єкт :

Ttime today;

Тоді можемо визначити посилання

Ttime & rtoday=today;

rtoday-це посилання. Оскільки посилання посилається на вже існуючі об’єкти, при вході в область дії посилання конструктор класу не викликається і, відповідно, не викликається деструктор при виході з області дії.

Об’єкти-результати функцій.

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

Ttime newtime(void)

{Ttime t;

return t;}

Тоді ця функція може викликатись так:

Ttime anothertime=newtime();

При цьому результат , який вертається функцією newtime() копіюється в anothertime. Правда, в нашому випадку це не логічно. Адже аналогічні дій виконуються при оголошенні : Ttime anothertime;

Часто використовують посилання на об’єкт чи вказівник на об’єкт в якості результату функції:

Ttime *newtime(void)

{Ttime *p=new Ttime;

return p;}

Тоді можна використати newtime() для отримання нового об’єкта та присвоїти його адресу вказівнику на Ttime:

Ttime*tp=newtime();

Функції-посилання можна використовувати для посилання на існуючі об’єкти:

Ttime today;-глобальний об’єкт

Ttime &newtimer(void)

{return today;}

Тоді можемо оголосити посилання на today так:

Ttime & tr=newtimer();

Звичайно, описані вище елементарні приклади є синтаксичною ілюстрацією.

Масиви об’єктів .

Масив об’єктів синтаксично задається як звичайний масив:

Ttime tentimes[10];

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

main(void)

{ Ttime tentimes[10];

for(int i=0;i<10;i++) tentimes[i].display();

return 0;

}

Очевидно, що тут буде надруковано 10 однакових значень.

Можна ініціалізувати масив , наприклад, так:

main(void)

{

Ttime tarray[3]={ Ttime(),Ttime(8),Ttime(8,1)};

for(int i=0;i<3;i++) tarray[i].display();

return 0;

}

Масиви об’єктів можуть розміщуватись в кучі та адресуватись за допомогою вказівників:

main()

{Ttime* tarrayp;

tarrayp=new Ttime[6];

for(int i=0;i<6;i++)

tarrayp[i].display();

delete[ ] tarrayp;

return 0;

}

Відмітимо, що в цьому прикладі 6 разів викликається конструктор по замовчуванню при виділенні пам’яті оператором new та 6 разів викликається деструктор при звертанні до delete, яка вжита в специфічній формі - з квадратними дужками (C++ ігнорує будь-які значення всередині цих дужок)

Контрольні запитання

1. Як викликаються конструктори глобальних об’єктів ?

2. Коли не викликаються деструктори локальних об’єктів при завершенні роботи програми ?

3. Навести приклад виділення пам’яті для екземпляра класу, що має лише конструктори з параметрами.

4. Коли не викликаються наявні конструктори при створенні екземпляра класу (і , відповідно, деструктори) ?

5. Чому при знищенні масиву об’єктів необхідно використовувати специфічну форму оператора delete ?

Завдання 5:

1. Описати масив об’єктів (що мають деструктори з відповідними повідомленнями) та проілюструвати роботу оператора delete:

delete a;

delete [ ] a;

delete &a[3];

delete &a[(int)(sizeof(a)/sizeof(a[0]))];

2. Написати функцію ret(), що має параметром індекс масиву об’єктів та повертає посилання на відповідний елемент.

3. Використовуючи функцію ret(), написати програму сортування масиву об’єктів за значеннями відповідних полів.

4. Модифікувати програми завдання 4.3( а)-б) ) так, щоб вони закінчувалася викликом функції exit(). Прослідкувати, як при цьому викликаються деструктори.

5. Розглянути ситуацію, коли програми попереднього завдання закінчується викликом функції abort().