Принцип інкапсуляції даних і дій: структури, їх поля, функціональні поля структур, прямий і непрямий доступ до членів структури


Принцип інкапсуляції даних і дій

Об'єктне програмування

Зміст (обєктне програмування)

 

 

Структура дозволяє нам збирати разом декілька видів інформації, представленої

її членами. Так структура Employee є абстракцією службовця, до членів якої

внесено суттєву с точки зору управління кадрами інформацію — атрибути об'єкту

 

const short kMaxNameSize = 20;

struct Employee

{

char name [kMaxNameSize];

unsigned int id;

float salary;

}

 

 

Над об'єктами типу Employee виконують якісь дії, наприклад, створюють, роздруковують,

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

теж розмістити в структурі. Тоді їх називають методами . Наприклад,

помістимо у структуру функцію роздруку

 

struct Point

{

// Атрибути

double _x;

double _y;

// Методи

Point operator+(Point);

bool operator==(Point);

double modulus ();

double phi ();

}

Кажуть, що атрибути дають нам абстракцію сутності об'єкту, представленого структурою, а методи — абстракцію поведінки .

 

Інший приклад — це вже згадані раніше точки площини разом з операціями додавання, порівняння, тощо

 

struct Point

{

// Атрибути

double _x;

double _y;

// Методи

Point operator+(Point);

bool operator==(Point);

double modulus ();

double phi ();

}

 

 

Для операцій домовилися зберегти традиційне позначення. Якщо виклик функції

modulus() об'єктом u позначається u.modulus() , то виклик операції додавання

об'єкту v позначають через u+v , а не u.+(v) , як цього вимагала б об'єктна

нотація.

 

Структури дають нам досить простий тип інкапсуляції ( encapsulation )

— об'єднання елементів з метою створення нової сутності. Найпростіша інкапсуляція

— це підпрограма, яка об'єднує інструкції, необхідні для досягнення певного

результату.

 

Структури можна створювати у звичний спосіб,

 

Point u;

 

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

 

u._x =1.0; u._y = 1.0;

 

або ініціалізуючи їх як масиви, наприклад,

 

Point v={1.0, 1.0};

 

Інкапсуляція змінила також сигнатуру операцій, оскільки інкапсульована у структуру

функція вже знає одну точку (перший доданок), тому аргументом задаємо лише

другу. Заголовок читається так: операція додавання, інкапсульована до структури

Point має один аргумент типу Point і повертає результат типу Point.

 

Визначення цієї операції можна розмістити всередині структури, а можна зовні.

В останньому випадку вживається вже відомий оператор розв'язання області видимості

::. Перший аргумент оператора розв'язання області видимості вказує на структуру,

яка задає нову область видимості інкапсульованих у структуру одиниць. Інкапсуляція

ділить об'єкт на дві частини: інтерфейс і реалізацію . Вище

ми записали інтерфейс, а так записується реалізація методів. Читаємо: оператор

додавання + із структури Point.

 

Point Point::operator+(Point v)

{

Point w;

w._x = _x + v._x;

w._y = _y + v._y;

return w;

}

 

Так само порівняння на рівність

 

bool operator== (Point v)

{

return (_x == v._x) && (_y == v._y);

}

 

А функції обчислення модуля і аргументу взагалі не потребує параметрів

 

#include <cmath>

double modulus ()

{

return sgrt(x*x+y*y);

}

double Point::phi ()

{

return atan(y/x);

}

 

 

Ось реалізація методу структури Employee

 

void Employee::printEmployee()

 

{

 

cout << "-----\n";

cout << "Прізвище: " << name << "\n";

cout << "ID: " << id << "\n";

cout << "Оклад: " << salary << "\n";

cout << "-----\n";

 

}

 

Завдяки інкапсуляції, функція бачить без додаткового уточнення за допомогою

кваліфікатора члени саме того об'єкту, який викликав цю функцію. Хоча сама

функція спільна для всіх об'єктів даного типу. Кажуть, що структуровані об'єкти

володіють атрибутами і розділяють методи. Ось приклад, в якому фігурують два

об'єкти. Як звичайно, структуровані об'єкти можуть іменуватися іменами або

указниками. Правда, у випадку указників ініціалізація дещо складніша. В повному

обсязі ми розглянемо її в наступному підрозділі

 

Employee employee1 = {"Клічко", 1, 300.0 };

Employee employee2 = {"Ребров", 2, 200.0 };

Employee *employeePtr;

employeePtr = &employee2;

employee1.printEmployee();

employeePtr->printEmployee();

 

Ось схематичне зображення цих двох структурованих об'єктів