Розробка власного класу 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>