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

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

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

значення за замовчуванням, рівне нулю:

 

Account (const char *name, double open_balance = 0.0);

 

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

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

 

class Account {

public:

// конструктор за замовчуванням...

Account ();

// імена параметрів в оголошенні вказувати необовязково

Account (const char*, double=0.0);

const char* name () { return name; }

// ...

private:

// ...

};

Нижче наведені два приклади правильного визначення обєкта класу Account, де конструкторові передається один або два аргументи:

 

int main ()

{

// правильно: в обох випадках викликається конструктор

// с двома параметрами

Account acct ("Ethan Stern");

Account *pact = new Account ("Michael Lieberman", 5000);

if (strcmp (acct. name (), pact->name ()))

// ...

}

 

C++ вимагає, щоб конструктор застосовувався до певного обєкта до його першого використання. Це означає, що як для acct, так і для обєкта, на який указує pact, конструктор буде викликаний перед перевіркою в інструкції if.

Компілятор перебудовує нашу програму, вставляючи виклики конструкторів.

От як, цілком ймовірно, буде модифіковане визначення acct усередині main ():

 

// псевдокод на C++,

// іллюструючий внутрішню вставку конструктора

int main ()

{

Account acct;

acct. Account:: Account ("Ethan Stern", 0.0);

// ...

}

Звичайно, якщо конструктор визначений як вбудований, то він підставляється в точці виклику.

Обробка оператора new трохи складніше. Конструктор викликається тільки тоді, коли він успішно виділив память. Модифікація визначення pact у трохи спрощеному виді виглядає так:

 

// псевдокод на C++,

// іллюструючий внутрішню вставку конструктора при обробці new

int main ()

{

// ...

Account *pact;

try {

pact = _new (sizeof (Account));

pact->Acct. Account:: Account (

"Michael Liebarman", 5000.0);

}

catch (std:: bad_alloc) {

// оператор new закінчився невдачею:

// конструктор не викликається

}

// ...

}

 

Існує три в загальному випадку еквівалентні форми завдання аргументів конструктора:

 

// загалом ці конструктори еквівалентні

Account acct1 ("Anna Press");

Account acct2 = Account ("Anna Press");

Account acct3 = "Anna Press";

 

Форма acct3 може використовуватися тільки при завданні єдиного аргументу. Якщо аргументів два або більше, рекомендовано користуватися формою acct1, хоча припустимо й acct2.

 

// рекомендує форма, що, виклику конструктора

Account acct1 ("Anna Press");

 

Визначати обєкт класу, не вказуючи списку фактичних аргументів, можна в тому випадку, якщо в ньому або обявлений конструктор за замовчуванням, або взагалі немає обяв конструкторів. Якщо в класі обявлений хоча б один конструктор, то не дозволяється визначати обєкт класу, не викликаючи жодного з них. Зокрема, якщо в класі визначений конструктор, що приймає один або більше параметрів, але не визначений конструктор за замовчуванням, то в кожному визначенні обєкта такого класу повинні бути присутнім необхідні аргументи. Можна заперечити, що не має змісту визначати конструктор за замовчуванням для класу Account, оскільки не буває рахунків без імені власника. У переглянутій версії класу Account такий конструктор виключений:

 

class Account {

public:

// імена параметрів в оголошенні вказувати необовязково

Account (const char*, double=0.0);

const char* name () { return name; }

// ...

private:

// ...

};

Тепер при оголошенні кожного обєкта Account у конструкторі обовязково треба вказати як мінімум аргумент типу C-рядка, але це швидше за все безглуздо. Чому? Контейнерні класи (наприклад, vector) вимагають, щоб для класу елементів, що поміщають у них, був або заданий конструктор за замовчуванням, або взагалі ніяких конструкторів. Аналогічна ситуація має місце при виділенні динамічного масиву обєктів класу. Так, що інструкція викликала б помилку компіляції для нової версії Account:

 

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

Account *pact = new Account [new_client_cnt];

 

На практиці часто потрібно задавати конструктор за замовчуванням, якщо є які-небудь інші конструктори.

А якщо для класу немає розумних значень за замовчуванням? Наприклад, клас Account вимагає задавати для будь-якого обєкта прізвище власника рахунку.

У такому випадку найкраще встановити стан обєкта так, щоб було видно, що він ще не ініціалізований коректними значеннями:

 

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

inline Account:: Account () {

_name = 0;

_balance = 0.0;

_acct_nmbr = 0;

}

 

Однак у функції-члени класу Account прийдеться включити перевірку цілісності обєкта перед його використанням.

Існує й альтернативний синтаксис: список ініціалізації членів, у якому через кому вказуються імена й початкові значення. Нап?/p>