Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Класи і об'єкти, члени класів

Класи і об'єкти, члени класів: атрибути і (класні) функції (function member), конструктори, деструктори, позакласні функції, утиліти класів; область видимості і права доступу: відкриті і закриті члени, порушення прав доступу, дружні функції

 

Побудована досі інкапсуляція має серйозний недолік, який ілюструється наступним

кодом:

 

employee1.name[3]=’о’;

employee1.name[7]=’в’;

employee1.name[8]=’а’;

employee1.name[9]=’\0’;

 

 

Поки що структури зовсім прозорі. Вони інкапсулюють свої члени, але дозволяють

доступ до них усім, хто бачить самі структури. Використання, а ще гірше, несанкціонована

зміна атрибутів залишаються неконтрольованими. В найбільш послідовному виді

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

Як і структура, клас складається із членів: атрибутів і методів. Він ділиться

на відкриту (public) і закриту (private)

частини. Головна відмінність від структур полягає у правилі замовчування. Відкриту

частину класу визначають явно. Все, що не позначено відкритим, закрите. Структури

звичайно відкриті, хоча можливе визначення закритої частини структури. Цим

користуються рідко.

 

class Point

{

// Атрибути

private:

double _x;

double _y;

// Методи

public:

Point (double a=0, double b=0);

Point operator+(Point);

bool operator==(Point);

double modulus ();

double phi ();

}

 

 

Одночасно ми доповнили визначення точки методом її ініціалізації. Створення

об'єкту — екземпляру класу (class instance) тепер інкапсулюється

у окрему програмну одиницю — метод, названий конструктором.

 

Point:: Point(double a, double b) {_x=a; _y=b;}

 

Визначення Point тепер необхідно доповнити оголошенням конструктора (зверніть

увагу на замовчувані значення його параметрів). Екземпляри точок створюються

тепер у такий спосіб

 

Point u(); //u._x == 0, u._y == 0

Point v(1.0, 2.0);

Point *p = new Point(1.0, -1.0);

 

 

Те ж саме стосується класу Employee

 

const short kMaxNameSize = 20;

class Employee

{

// Атрибути

private:

char name [kMaxNameSize];

unsigned int id;

float salary;

// Методи

public:

Employee(char*, unsigned int, float);

void printEmployee();

}

 

Тепер доступ зовні до атрибутів закрито, а ось реалізація конструктора

 

Employee::Employee(char *n, unsigned int i, float s)

{

strncpy(name, n, kMaxNameSize);

name[kMaxNameSize-1]='\0';

id = i;

salary = s;

cout << "Зареєстровано службовця” << "\n";

printEmployee();

}

 

Метод, симетричний конструктору, називається деструктором. Навіть

якщо у визначенні класу конструктори і деструктори відсутні (це можливо), система

програмування наділяє клас замовчуваними порожніми конструктором і деструктором.

Тому конструктор і деструктор є завжди. Щоб проблему стало краще видно, розглянемо

трохи складніший варіант структури EmployeeP, в якому передбачено виділення

динамічної пам'яті

 

class EmployeeP

{

// Атрибути

private:

char * name;

unsigned int id;

float salary;

// Методи

public:

EmployeeP(char*, unsigned int, float);

~EmployeeP();

void printEmployee();

};

 

Тепер пам'ять для прізвища виділяється в конструкторі

 

EmployeeP::EmployeeP(char *n, unsigned int i, float s)

{

name = new char[strlen(n)+1];

strcpy(name, n);

id = i;

salary = s;

};

 

 

Знову розглянемо два визначення

 

EmployeeP employee1("Клічко", 1, 300.0);

EmployeeP *employee2;

employee2 = new EmployeeP("Ребров", 2, 200.0);

 

 

Об'єкт employee1 автоматичний, він знищується компілятором автоматично при

виході з блоку. Об'єкт employee2 динамічний, його необхідно знищувати явно

інструкцією delete. Але в обох випадках рядок name продовжує зберігатися в

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

неявно в момент закінчення життя відповідного об'єкта.

 

EmployeeP::~EmployeeP()

{

delete [] name;

}

 

 

Поява класів не ліквідує звичайних функцій, не інкапсульованих у класах. Образно

їх можна називати позакласними функціями (non-member function).

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

кінцевими точками:

 

double prod (Point u, Point v)

{

return u.modulus()*v.modulus()*cos(u.phi()-v.phi());

}

 

 

Позакласні функції, параметрами яких служать екземпляри певних класів, називають утилітами цих

класів. Одні класи можуть використовуватися у визначенні інших, наприклад,

клас трикутників використовує (агрегує) клас точок

 

class Triangle

{

Point a, b, c;

public:

Triangle (Point, Point, Point);

perimeter();

square();

}

 

 

Звичайно для атрибутів у класах передбачають методи доступу — парні функції

запису і читання атрибуту. Скажімо для класу точок це були б функції

 

void Point:: setX (double);

double Point:: readX();

 

void Point:: setY (double);

double Point:: readY();

 

або

double& Point:: X (double);

double& Point:: Y (double);

 

 

Загальнодоступність методів доступу корисна не завжди. Скажімо візьмемо задачу

нарахування зарплати. Відомість про зарплату кожного співробітника є конфіденційною

інформацією, а тому в клас не доцільно мати відкритий метод читання окладу,

не кажучи вже про метод встановлення окладу. Припустимо, що за нарахування

запрали відповідатиме метод printCheck класу Payroll

 

void Payroll:: printCheck(EmployeeP *payee)

{

cout << "Pay $" << payee->getSalary()

<< " to the order of "

<< payee->getName() << "...\n\n";

}

 

 

Порушення прав доступу відбувається шляхом визначення дружнього класу або

дружньої функції. Нею може бути метод іншого класу або навіть позакласна функція,

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

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

вибрати потрібну. Дружній об'єкт одержує винятковий доступ до закритої частини

класу. Друзів обирають обережно!

 

class EmployeeP

{

friend void Payroll:: printCheck(EmployeeP *);

// також:

friend class Employer;

// крім них:

friend bool operator>

(const EmployeeP&, const EmployeeP&);

// Атрибути

private:

char * name;

unsigned int id;

float salary;

// Методи

EmployeeP(char*, unsigned int, float);

float getSalary();

public:

~EmployeeP();

void printEmployee();

char* getName();

};

 

 

Ось операція порівняння службовців за окладами

 

bool operator>(const EmployeeP& e1, const EmployeeP& e2)

{

return e1.getSalary()>e2.getSalary();

}

 

 

Доповніть клас EmployeeP атрибутом, що зберігатиме дату зарахування на роботу

і визначіть порівняння службовців за стажем роботи.

 

Закритим може виявитися навіть конструктор. Можна домовитися, що створення

службовця є операцією, що вимагає особливих повноважень. Ось чому ми перенесли

конструктор у закриту частину та призначили дружнім класом клас Employer —

службовця на роботу приймає роботодавець

 

EmployeeP * Employer::

createEmployee(char *n, unsigned int i, float s)

{

EmployeeP *anEmployee;

anEmployee = new EmployeeP (n, i, s);

return anEmployee;

}

 

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

інформації (information hiding). Клас Employee служить програмною

абстракцією службовця, клас Employer — працедавця, клас Payroll — відділу

зарплати. Кожен клас інкапсулює в собі дані і методи, приховуючи реалізацію

методів і зображення даних. Частина даних видима або доступна через відповідні

методи доступу всім, інша — лише привілейованим об'єктам.

 

 

5.2 Інтерфейс класу, реалізація класу; визначення і оголошення класу

Інтерфейс класу, реалізація класу; визначення і оголошення класу

 

Традиційно інтерфейс і реалізацію класу розміщують у різних файлах, як це

було з оголошеннями і визначеннями об'єктів. Інтерфейс записують у заголовні

файли. Ось приклад заголовного файлу для класу точок

 

//Point.h

#ifndef POINT_H

#define POINT_H

class Point

{

// Атрибути

private:

double _x;

double _y;

// Методи

public:

Point (double a=0, double b=0);

Point operator+(Point);

bool operator==(Point);

double modulus ();

double phi ();

}

#endif

 

Ось файл реалізації

 

//Point.cpp

# include ”Point.h”

#include <cmath>

Point:: Point(double a, double b)

{

_x=a; _y=b;

}

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);

}

double modulus ()

{

return sgrt(_x*_x+_y*_y);

}

double Point::phi ()

{

return atan(_y/_x);

}

//Кінець Point.cpp

 

Буває зовсім коротке оголошення класу, наприклад,

 

//Payroll.h

#ifndef PAYROLL_H

@define PAYROLL_H

class EmployeeP;

class Payroll

{

…………………………………

void printCheck(EmployeeP *)

}

#endif

 

Без оголошення класу EmployeeP компілятор не зміг би відкомпілювати оголошення

функції printCheck, де EmployeeP використовується як тип параметру. Інтерфейс

класу EmployeeP знадобиться лише у файлі Payroll.cpp, де буде визначатися

реалізація. Туди і помістимо #include

 

//Payroll.cpp

#include ”Payroll.h”

#include ”EmployeeP.h’

 

 

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

включення додаткових файлів.

 

 

<== предыдущая лекция | следующая лекция ==>
Принцип інкапсуляції даних і дій: структури, їх поля, функціональні поля структур, прямий і непрямий доступ до членів структури | Cтатичні члени класів і статичні класні функції
Поделиться с друзьями:


Дата добавления: 2014-01-04; Просмотров: 389; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.076 сек.