Смекни!
smekni.com

Розробка власного класу STRING (стр. 2 из 16)

1.3 Доступ до елементів структури

Для доступу до елементів структури (або класу) використовуються операції доступу до елементів - операція крапка () і операція стрілка (->).

Операція крапка звертається до елемента структури (або класу) по імені змінної об'єкта або по посиланню на об'єкт.

Наприклад, щоб надрукувати елемент hour структури timeObject використається оператор

cout << timeObject. hour;

Операція стрільця, що складається зі знака мінус (-) і знака більше (>), записаних без пропусків, забезпечує доступ до елемента структури (або класу) через вказівник на об'єкт. Припустимо, що вказівник timePtr був уже об’явлений як посилання на об'єкт типу Time і що адреса структури timeObiect була вже присвоєна timePtr. Тоді, щоб надрукувати елемент hour структури timeObject з вказівником timePtr, можна використати оператор

cout << timePtr->hour;

Вираз timePtr->hour еквівалентний (*timePtr). hour, що розіменовує вказівник і робить доступним елемент hour через операцію крапка. Дужки потрібні тому, що операція крапка має більш високий пріоритет, ніж операція розіменування вказівника (*). Операції стрілка й крапка поряд із круглими й квадратними дужками мають другий найвищий пріоритет (після операції дозволу області дії) і асоціативності зліва направо.

1.4 Використання визначеного користувачем типу Time за допомогою Struct

Програма на мал.1 створює визначений користувачем тип структури Time із трьома цілими елементами: hour, minute і second. Програма визначає єдину структуру типу Time, названу dinnerTime, і використовує операцію крапка для присвоєння елементам структури початкових значень 18 для hour, 30 для minute і 0 для second. Потім програма друкує час у військовому (24-годинному) і стандартному (12-годинному) форматах. Помітимо, що функції друку приймають посилання на постійні структури типу Time. Це є причиною того, що структури Time передаються друкуючим функціям по посиланню - цим виключаються накладні витрати на копіювання, пов'язані з передачею структур функціям за значенням, а використання const запобігає зміні структури типу Time функціями друку. Далі ми обговоримо об'єкти const і функції-елементи const.

Порада з підвищення ефективності: Щоб уникнути накладних витрат, пов’язаних із передачею по значенню й одержати користь захисту початкових даних від зміни, передавайте аргументи великого розміру як посилання const.

Існують перешкоди створенню нових типів даних зазначеним способом за допомогою структур. Оскільки ініціалізація структур спеціально не потрібна, можна мати дані без початкових значень і випливаючи звідси проблеми. Навіть якщо дані одержали початкові значення, можливо, це було зроблено невірно. Неправильні значення можуть бути привласнені елементам структури (як ми зробили на мал.1), тому що програма має прямий доступ до даних. Програма присвоїла невірні значення всім трьом елементам об'єкта dinnerTime типу Time. Якщо реалізація struct зміниться (наприклад, час тепер буде представляється як число секунд після півночі), то всі програми, які використовують struct, потрібно буде змінити. Не існує ніякого "інтерфейсу", гарантуючого те, що програміст правильно використає тип даних і що дані є несуперечливими.

// Створення структури, завдання й друк її елементів.

#include <iostream. h>

struct Time { // визначення структури

int hour; // 0-23

int minute; // 0-59

int second; // 0-59 };

void printMilitary (const Time &); // прототип void printStandard (const Time &); // прототип

main ()

{

Time dinnerTime; // змінна нового типу Time

// завдання елементам правильні значення dinnerTime. hour = 18; dinnerTime. minute = 30; dinnerTime. second = 0;

cout " "Обід відбудеться в ";

printMilitary (dinnerTime);

cout " " за військовим часом," " endl

<< "що відповідає "; printStandard{dinnerTime); cout << " за стандартним часом." << endl;

// завдання елементам неправильних значень

dinnerTime. hour = 29;

dinnerTime. minute = 73; dinnerTime. second = 103;

cout " endl << "Час із неправильними значеннями: "; printMilitary (dinnerTime); cout << endl; return 0;

// Друк часу у військовому форматі void printMilitary (const Time &t)

{

cout " (t. hour < 10?"0": "")" t. hour

"": "" (t. minute < 10?"0": "")" t. minute

"": "" (t. second < 10?"0": "")" t. second;

}

// друк часу в стандартному форматі

void printStandard (const Time &t)

{

cout " ( (t. hour == 0 || t. hour == 12)? 12: t. hour%12)" ": "" (t. minute < 10?"0": "")" t. minute " ": "" (t. second < 10?"0": "")" t. second " (t. hour < 12?" AM": " PM");

}


Обід відбудеться в 18: 30: 00 за військовим часом,

що відповідає 6: 30: 00 РМ за стандартним часом.

Час із неправильними значеннями: 29: 73: 103

Мал.1. Створення структури, завдання й друк її елементів

Існують і інші проблеми, пов'язані зі структурами в стилі С. У С структури не можуть бути надруковані як єдине ціле, тільки по одному елементу з відповідним форматом кожного. Для друку елементів структури в якому-небудь потрібному форматі повинна бути написана функція. "Перевантаження операцій" покаже, як перевантажити операцію ", щоб надати можливість простого друку об'єктів типу структура (C++ розширює поняття структури) або типу клас. У С структури не можна порівнювати в цілком, їх потрібно порівнювати елемент за елементом. Далі покажемо, як перевантажити операції перевірки рівності й відношення, щоб можна було в С++ порівнювати об'єкти типів структура й клас.

У наступному розділі ми знову використаємо нашу структуру Time, але вже як клас, і продемонструємо деякі переваги створення таких, так званих абстрактних типів даних, як класи. Ми побачимо, що класи й структури в C++ можна використовувати майже однаково. Різниця між ними складається в доступності за замовчуванням елементів кожного із цих типів. Це буде більш детально пояснено пізніше.

1.5 Використання абстрактного типу даних Time за допомогою класу

Класи надають програмістові можливість моделювати об'єкти, які мають атрибути (представлені як дані-елементи) і варіанти поведінки або операції (представлені як функції-елементи). Типи, що містять дані-елементи й функції-елементи, звичайно визначаються в C++ за допомогою ключового слова class.

Функції-елементи іноді в інших об’єктно-орієнтовних мовах називають методами, вони викликаються у відповідь на повідомлення, що посилаються об'єкту. Повідомлення відповідає виклику функції-елемента.

Коли клас визначений, ім'я класу може бути використане для об’явлення об'єкта цього класу. Мал.1 містить просте визначення класу Time.

Визначення нашого класу Time починається із ключового слова class. Тіло визначення класу береться у фігурні дужки ({ }). Визначення класу закінчується крапкою з комою. Визначення нашого класу Time, як і нашої структури Time, містить три цілих елементи hour, minute і second.

сlass Time {

public:

Time ();

void setTime (int, int, int);

void printMilitary ();

void printStandatd (); private:

int hour; // 0-23

int minute; // 0 - 59

int second; // 0-59

};

Мал.1 Просте визначення класу

Інші частини визначення класу - нові. Мітки public: (відкрита) і private: закрита) називаються специфікаторами доступу до елементів. Будь-які дані-елементи й функції-елементи, об’явлені після специфікатора доступу до елементів public: (і до наступного специфікатора доступу до елементів), доступні при будь-якому звертанні програми до об'єкта класу Time. Будь-які дані-елементи й функції-елементи, об’явлені після специфікатора доступу до елементів private: (і до наступного специфікатора доступу до елементів), доступні тільки функціям-елементам цього класу. Специфікатори доступу до елементів завжди закінчуються двокрапкою (:) і можуть з'являтися у визначенні класу багато разів і в будь-якому порядку. Надалі в тексті нашої роботи ми будемо використовувати записи специфікаторів доступу до елементів у вигляді public і private (без двокрапки).

Гарний стиль програмування: Використовуйте при визначенні класу кожний специфікатор доступу до елементів тільки один раз, що зробить програму більш ясною й простій для читання. Розміщайте першими елементи public, що є загальнодоступними.

Визначення класу в нашій програмі містить після специфікатора доступу до елементів public прототипи наступних чотирьох функцій-елементів: Time, setTime, printMilitary і printStandard. Це - відкриті функції-елементи або відкритий інтерфейс послуг класу. Ці функції будуть використовуватися клієнтами класу (тобто частинами програми, що грають роль користувачів) для маніпуляцій з даними цього класу.

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

Після специфікатора доступу до елементів private слідують три цілих елементи. Це говорить про те, що ці дані-елементи класу є доступними тільки функціям-елементам класу й, як ми побачимо далі, "друзям" класу. Таким чином, дані-елементи можуть бути доступні тільки чотирьом функціям, прототипи яких включені у визначення цього класу (або друзів цього класу). Звичайно дані-елементи перераховуються в частині private, а функції-елементи - у частині public. Як ми побачимо далі, можна мати функції-елементи private і дані public; останнє не типовим й вважається в програмуванні поганим тоном.

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


Time sunset, // об'єкт типу Time

arrayOfTimes [5], // масив об'єктів типу Time

*pointerToTime, // вказівник на об’єкт типу Time

&dinnerTime = sunset; // посилання на об'єкт типу Time

Ім'я класу стає новим специфікатором типу. Може існувати безліч об'єктів класу як і безліч змінних типу, наприклад, такого, як int. Програміст по мірі необхідності може створювати нові типи класів. Це одна з багатьох причин, з яких C++ є розширюваною мовою.