Деструктори класу. Загальнодоступні та приватні деструктори. Приклади використання деструкторів. Відмінності між конструкторами та деструкторами

Деструктори. Визначення деструктора. Загальнодоступні та приватні деструктори. Приклади використання деструкторів. Відмінності між конструкторами та деструкторами


Зміст



1. Яке призначення деструктора в класі?

Деструктор, як і конструктор, відноситься до спеціальних функцій класу. Деструктор – це спеціальний метод, що викликається при видаленні об‘єкту. Як правило, деструктор використовується для звільнення пам‘яті, динамічно виділеної під внутрішні дані класу. Можуть бути й інші випадки застосування деструктора.

Деструктор – це зворотна по відношенню до конструктора функція.

Ім‘я деструктора співпадає з іменем класу, перед яким слідує символ ‘~’. Наприклад, якщо клас має ім‘я CMyClass, тоді ім’я деструктора буде ~CMyClass().

2. Приклад використання загальнодоступного деструктора

Нехай задано клас, що визначає масив структур типу DATE. Кожна структура в масиві описує дату в форматі: число, місяць, рік. У класі оголошено ряд конструкторів, методів а також деструктор, який звільняє пам’ять для масиву.

Загальний код модуля, в якому оголошується структуру та клас.

// структура, що реалізує дату
struct DATE
{
    int day;
    int month;
    int year;
};

// клас, що реалізує масив структур типу DATE
class CDates
{
    int n;
    DATE *A; // масив структур

    public:
    CDates(void); // конструктор за замовчуванням
    ~CDates(void); // деструктор

    // методи класу
    void SetN(int nn); // встановити нове значення n, перевиділити пам'ять для масиву A
    DATE GetDATE(int index); // повернути значення структури з індексом index
};

// конструктор за замовчуванням
CDates::CDates(void)
{
    n = 0;
}

// деструктор
CDates::~CDates(void)
{
    // звільнення пам'яті, виділеної для масиву структур
    delete A;
}

// встановити нове значення n
void CDates::SetN(int nn)
{
    // 1. Звільнити попередню пам'ять
    // звільнити пам'ять, виділену під масив структур
    delete A;

    // 2. Встановити нове n
    n = nn;

    // 3. Виділити пам'ять для масиву покажчиків на структуру типу (DATE *)
    A = new DATE[n];

    // заповнити значення кожної структури довільними значенням
    for (int i=0; i<n; i++)
    {
        A[i].day = i;
        A[i].month = i%12 + 1;
        A[i].year = 1000*i;
    }
}

// повернути значення структури з індексом DATE
DATE CDates::GetDATE(int index)
{
    return (DATE)A[index];
}

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

CDates CD; // оголосити об'єкт типу CDates, викликається конструктор за замовчуванням

// встановити нове значення n
CD.SetN(8);

// перевірка
int t;
DATE D;
D = CD.GetDATE(5); // взяти структуру з індексом 5

t = D.day; // t = 5
t = D.year; // t = 5000

// після виходу з методу, об'єкт CD знищується, а, отже, викликається деструктор ~CDates
// який звільняє пам'ять для масиву A в класі

3. Чи можна деструктор оголосити в розділі private?

Так, можна. Такий деструктор називається приватним деструктором.

4. В яких випадках доцільно оголошувати приватні деструктори?

Використання приватних деструкторів доцільно у тих випадках, коли звичайним користувачам забороняється звільняти пам’ять для раніше створених об’єктів (знищувати раніше створені об’єкти).

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

Якщо в класі оголошено приватний деструктор, то виникають наступні обмеження:

  • неможливо створити автоматичний об’єкт класу (об’єкт класу, що оголошується в деякому методі);
  • неможливо створити статичний об’єкт;
  • неможливо створити глобальний об’єкт класу.

Це зв’язано з тим, що такі об’єкти в подальшому неможливо буде знищити.

Наприклад. Нехай задано клас, в якому оголошено приватний деструктор.

class CMyInt
{
    private:
    int n; // кількість елементів масиву

    // деструктор, оголошений в розділі private
    ~CMyInt(void);

    public:
    CMyInt(void);

    // методи класу
    void SetN(int nn) { n = nn; }
    int GetN(void) { return n; }
};

Якщо спробувати створити об’єкт класу в іншому програмному коді на зразок

CMyInt MI;

то компілятор видасть помилку

'CMyInt::~MyInt': cannot access private member declared in class 'CMyInt'

Однак, можна оголошувати покажчик на клас CMyInt. Наступний опис буде добрим

// приватний деструктор
CMyInt * pMI = new CMyInt; // можна оголошувати покажчик на клас, що визначає приватний деструктор

6. Чи може деструктор мати параметри?

Деструктор не може мати параметрів.

7. Які основні відмінності між використанням конструкторів і деструкторів у класах?

При використанні в класі, між конструктором і деструктором можна визначити такі основні відмінності:

  • деструкторам не можна передавати параметри, конструкторам можна;
  • деструктори можуть бути віртуальні, конструктори – ні;
  • при оголошенні класу, можна оголосити тільки один деструктор. Однак, конструкторів можна оголошувати скільки завгодно. Головне, щоб вони відрізнялись сигнатурою.


Зв’язані теми