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

Void getaLine(string& inStr); // Отримання рядка тексту char getaCharO; //Отримання символу

class tenant { // Мешканці

private:

string name; // Ім'я мешканця

Int aptNumber; // Номер кімнати мешканця

// Тут може бути будь-яка інша інформація про мешканця,

// наприклад, номер телефону і т.ін.

public:

tenant(string n, int aNo);

~tenant();

int getAptNumber(); // Потрібно для використання в множині friend bool operator < (const tenant&, const tenant&); friend bool operator == (const tenant&, const tenant&);

// Для операцій введення/виведення

friend ostream& operator« (ostream&, const tenant&);

}; // <—> Кінець оголошення класу tenant // Функціональний об'єкт для порівняння імен мешканців class compareTenants {

public:

bool operator 0 (tenant*, tenant*) const;

};

// >—> Клас tenantList class tenantList { private:

// Встановити покажчики на мешканців set<tenant*, compareTenants> setPtrsTens; set<tenant*, compareTenants>::iterator iter; public:

~tenantList(); // Оголошення деструктора (Видалення мешканців) void insertTenant(tenant*); // Внесення мешканця в перелік int getAptNo(string); // Повертає номер кімнати

Void DisplayO; // Виведення переліку мешканців

};

// <—> Кінець оголошення класу tenantList

class tenantlnputScreen { private:

tenantList* ptrTenantList; string tName; int aptNo; public:

tenantlnputScreen(tenantList* ptrTL): ptrTenantList(ptrTL)

{І* тут порожньо */} void getTenant();

}; // <—> Кінець класу tenantlnputScreen

// Один рядок таблиці прибутку: адреса і 12 місячних плат

class rentRow {

private:

Int aptNo; float rent[12]; public:

rentRow(int); // Оголошення конструктора з одним параметром

Void setRent(int, float); // Запис плати за місяць

float getSumOfRow(); // Сума платежів з одного рядка

// Потрібно для збереження в множині friend bool operator < (const rentRow&, const rentRow&); friend bool operator == (const rentRow&, const rentRow&); friend ostream& operator« (ostream&, const rentRow&); // Для виведення }; // <—> Кінець класу rentRow

// Функціональний об'єкт порівняння об'єктів rentRows

class compareRows {

public:

bool operator 0 (rentRow*, rentRow*) const;

};

class rentRecord { private:

// Множину покажчиків на об'єкти rentRow (по одному на мешканця) set<rentRow*, compareRows> setPtrsRR; set<rentRow*, compareRows>::iterator iter; public:

~rentRecord();

Void insertRent(int, int, float); void DisplayO;

float getSumOfRents(); // Сума усіх платежів }; // <—> Кінець класу rentRecord

class rentlnputScreen { private:

tenantList* ptrTenantList; rentRecord* ptrRentRecord; string renterName; float rentPaid; int month; int aptNo; public:

rentlnputScreen(tenantList* ptrTL rentRecord* ptrRR): ptrTenantList(ptrTL), ptrRentRecord(ptrRR)

{/*тут пусто*/}

void getRent(); // Орендна плата одного мешканця за один місяць }; // <—> Кінець класу rentlnputScreen

class expense { public:

Int month, day; string category, payee; float amount; expense() {}

expense(int m, int d, string c, string p, float a):

month(m), day(d), category(c), payee(p), amount(a)

{/* тут порожньо! */}

// Потрібно для зберігання в множині

friend bool operator < (const expense&, const expense&);

friend bool operator == (const expense&, const expense&);

// Потрібно для виведення

friend ostream& operator« (ostream&, const expense&);

}; // <—> Кінець класу expense // Функціональний об'єкт порівняння витрат class compareDates { public:

bool operator 0 (expense*, expense*) const;

};

// Функціональний об'єкт порівняння витрат

class compareCategories {

public:

bool operator 0 (expense*, expense*) const;

};

class expenseRecord { private:

// Вектор покажчиків на витрати vector<expense*> vectPtrsExpenses; vector<expense*>::iterator iter; public:

~expenseRecord(); void insertExp(expense*); void DisplayO;

float displaySummaryO; // Потрібно для річного звіту }; // <—> Кінець класу expenseRecord

class expenselnputScreen { private:

expenseRecord* ptrExpenseRecord; public:

expenselnputScreen(expenseRecord*); void getExpenseO;

}; // <—> Кінець класу expenselnputScreen

class annualReport { private:

rentRecord* ptrRR; expenseRecord* ptrER; float expenses, rents; public:

annualReport(rentRecord*, expenseRecord*); void DisplayO;

}; // <—> Кінець класу annualReport

class userlnterface { private:

tenantList* ptrTenantList; tenantlnputScreen* ptrTenantlnputScreen; rentRecord* ptrRentRecord; rentlnputScreen* ptrRentlnputScreen; expenseRecord* ptrExpenseRecord; expenselnputScreen* ptrExpenselnputScreen; annualReport* ptr AnnualReport; char ch; public:

userlnterfaceO;

~userlnterface();

void interactO;

}; // <—> Кінець класу userlnterfac

// <—> Кінець файлу landlord.h

Оголошення класів - це просто. Більшість оголошень зростають безпосе­редньо з класів, створених за допомогою узятих з описів варіантів використання іменників, і відображаються на діаграмі класів. Тільки імена з багатослівних пот­рібно зробити однослівними. Наприклад, ім'я "Перелік мешканців" (Tenant List) перетворюється в TenantList.

У заголовному файлі було додано ще декілька допоміжних класів. Згодом ви­явиться, що ми зберігаємо покажчики на об'єкти в різних типах контейнерів STL. Це означає, що ми повинні порівнювати об'єкти цих контейнерів так, як це описа­но в розд. 12 "Введення в стандартну бібліотеку шаблонів". Об'єктами порівняння насправді є класи compareTenants, compareRows, compareDates і compareCategories.

Описи атрибутів. Як уже було зазначено вище, багато атрибутів (методи) для кожного з класів є похідними з тих іменників, які самі не стали класами. Нап­риклад, name і aptNumber стали атрибутами класу tenant.

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

Складені значення (агрегати). Агрегатні зв'язки показані в трьох місцях на діаграмі класів. Зазвичай агрегати виявляють ті контейнери, які є атрибутами аг­регатного класу (тобто "цілого" класу, що містить "частини").

Ні за описами варіантів використання, ні за діаграмами класів неможливо вгадати, якого роду контейнери повинні використовуватися для цих агрегатів. Вам як програмістам доведеться самим щоразу вибирати відповідний контейнер для кожного складеного значення - будь-то простий масив, контейнер STL або що-небудь ще. У програмі landlord ми зробили такий вибір:

  • клас tenantList містить STL-множину покажчиків на об'єкти класу tenant;

  • клас rentRecord містить множину покажчиків на об'єкти класу rentRow;

  • клас expenseRecord містить вектор покажчиків на об'єкти класу expense.

Для tenantList і rentRecord ми вибрали множини, оскільки основним параметром є швидкий доступ до даних. Для expenseRecord вибрано вектор, тому що нам важ­ливо здійснювати швидке сортування і за датою, і за категоріями, а вектори дають змогу сортувати дані найефективніше.

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

Створення початкових *.срр файлів. У початкових файлах містяться тіла методів, які були оголошені в заголовному файлі. Написання коду програми цих

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

Нарешті ми, так би мовити, відокремили зерна від полови: mainO зберігаємо в одному коротенькому файлі lordApp.cpp, а визначення функцій, оголошених у заго­ловному файлі, - в іншому. У секції mainO створюється об'єкт userlnterface і викли­кається метод interactO- Наведемо файл, у якому зберігається main().

Код програми 14.2. Демонстрація програми lordApp.cpp

// Файл, що постачається клієнту.

#include "landlord, h"