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

Void Get(myClass &obj) // Передача об'єкта за посиланням

{

cout«"*р=" « obj.Put() « endl;

}

Int mainO

{

myClass ObjA(10); // Створення об'єкта класу

Get(ObjA);

getchO; return 0;

}

Оскільки об'єкт obj тепер передається за посиланням, то побітова копія аргу- мента не створюється, а отже, об'єкт не виходить з області видимості після завер­шення роботи функції GetO- Результати виконання цієї версії коду програми вигля­дають набагато краще від попередніх:

Виділення р-пам'яті звичайним конструктором

*р= 10

Звільнення р-пам'яті

Як бачимо, тут деструктор викликається тільки один раз, оскільки при пере­дачі за посиланням аргумента функції GetO побітова копія об'єкта не створюється.

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

  1. Особливості механізму повернення об'єктів функціями

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

Код програми 3.11. Демонстрація механізму повернення об'єкта функцією #include <vcl>

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

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

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

char str[80];

public:

Void Set(char*s) {strcpy(str, s);}

Void Show() {cout «"Рядок:" « str« endl;}

};

// Ця функція повертає об'єкт типу strClass. strClass InitO {

strClass obj; char str[80];

cout«"Введіть рядок:сіп » str;

obj.Set(str);

return obj;

}

Int mainO

{

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

Obj = lnit(); // Присвоюємо об'єкт, повернутий функцією lnit(), об'єкту Obj Obj.ShowO;

getchO; return 0;

}

У наведеному прикладі функція InitO створює локальний об'єкт obj класу strClass, а потім зчитує рядок з клавіатури. Цей рядок копіюється в рядок obj.str, піс­ля чого об'єкт obj повертається функцією lnit() і присвоюється об'єкту Obj у функції mainO-

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

Код програми 3.12. Демонстрація механізму появи помилки, яка виникає при поверненні об'єкта функцією

#include <vcl>

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

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

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

char *s; public:

strClass() {s = 0;}

-strClassO {if(s) delete[]s; cout«"Звільнення s-пам'яті" « endl;}

void Set(char *str) {s = new char[strlen(str)+1 ]; strcpy(s, str);} // Завантаження рядка.

void ShowO {cout«"s=" « s « endl;}

};

// Ця функція повертає об'єкт типу strClass. strClass InitO {

strClass obj; char str[80];

cout«"Введіть рядок:"; сіп » str;

obj.Set(str);

return obj;

}