Розробка власного класу STRING

Курсовой проект - Компьютеры, программирование

Другие курсовые по предмету Компьютеры, программирование

?иклад, конструктор за замовчуванням можна переписати в такий спосіб:

 

// конструктор за замовчуванням класу Account з використанням

// списку ініціалізації членів

inline Account::

Account ()

: _name (0),

_balance (0.0), _acct_nmbr (0)

{}

 

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

 

inline Account::

Account (const char* name, double opening_bal)

: _balance (opening_bal)

{

_name = new char [strlen (name) +1];

strcpy (_name, name);

_acct_nmbr = get_unique_acct_nmbr ();

}

 

Конструктор не можна обявляти із ключовими словами const або volatile, тому наведені записи невірні:

 

class Account {

public:

Account () const; // помилка

Account () volatile; // помилка

// ...

};

 

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

Розглянемо наступний фрагмент програми:

 

// у якімсь заголовному файлі

extern void print (const Account &acct);

// ...

int main ()

{

// перетворить рядок "oops" в обєкт класу Account

// за допомогою конструктора Account:: Account ("oops", 0.0)

print ("oops");

// ...

}

 

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

Ненавмисні неявні перетворення класів, наприклад трансформація "oops" в обєкт класу Account, виявилися джерелом помилок, що виявляють важко. Тому в стандарт C++ було додано ключове слово explicit, що говорить компіляторові, що такі перетворення не потрібні:

 

class Account {

public:

explicit Account (const char*, double=0.0);

};

 

Даний модифікатор застосуємо тільки до конструктора.

 

1.8 Конструктор копіювання

 

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

Часто почленна ініціалізація не забезпечує коректну дію класу. Тому ми явно визначаємо конструктор копіювання. У нашому класі Account це необхідно, інакше два обєкти будуть мати однакові номери рахунків, що заборонено специфікацією класу.

Конструктор копіювання приймає як формальний параметр посилання на обєкт класу (рекомендовано зі специфікатором const). Його реалізація:

 

inline Account::

Account (const Account &rhs)

: _balance (rhs. _balance)

{

_name = new char [strlen (rhs. _name) + 1];

strcpy (_name, rhs. _name);

// копіювати rhs. _acct_nmbr не можна

_acct_nmbr = get_unique_acct_nmbr ();

}

 

Коли ми пишемо:

 

Account acct2 (acct1);

 

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

 

1.9 Деструктор класу

 

Одна із цілей, що ставляться перед конструктором, - забезпечити автоматичне виділення ресурсу. Ми вже бачили в прикладі із класом Account конструктор, де за допомогою оператора new виділяється память для масиву символів і привласнюється унікальний номер рахунку. Можна також представити ситуацію, коли потрібно одержати монопольний доступ до поділюваної памяті або до критичної секції потоку. Для цього необхідна симетрична операція, що забезпечує автоматичне звільнення памяті або повернення ресурсу після завершення часу життя обєкта, - деструктор. Деструктор - це спеціальна обумовлена користувачем функція-член, що автоматично викликається, коли обєкт виходить із області видимості або коли до покажчика на обєкт застосовується операція delete. Імя цієї функції створено з імені класу з попереднім символом “тильда" (~). Деструктор не повертає значення й не приймає ніяких параметрів, а отже, не може бути перевантажений.

Хоча дозволяється визначати кілька таких функцій-членів, лише одна з них буде застосовуватися до всіх обєктів класу. От, наприклад, деструктор для нашого класу Account:

&