12.3  Инкапсуляция

Под инкапсуляцией понимается скрытие или помещение в капсулу некоторых данных, определяющих свойства и поведение объекта. Иными словами, инкапсуляция означает, что функции-элементы и структуры данных, определяющие свойства данного класса, рассматриваются в качестве единого целого. Это подразумевает «защиту» данных в пределах класса таким образом, что только элементы класса получают к ним доступ. В объектно-ориентированном программировании единицей инкапсуляции является объект.  В объектно-ориентированном программировании считается хорошим тоном закрывать все данные и функции-элементы описываемого класса от доступа «извне».

Компилятор C++ предоставляет программистам три уровня доступа к элементам объектов:

1) public    (общедоступный);

2) private   (закрытый);

3) protected (защищенный).

Элементы, объявленные общедоступными, будут доступны любому внешнему элементу класса, любой функции, элементу или выражению в программе, когда объект является видимым. Закрытые элементы доступны только членам – элементам своего же класса. Они не доступны извне, за исключением специальных функций, называемых "дружественными". К защищенным элементам имеют доступ лишь некоторые из объектов. Они доступны только элементам своего класса и любым его потомкам. Поэтому защищенные элементы занимают промежуточное положение между общедоступными и закрытыми.

Примечание: закрытые элементы не доступны потомкам своего класса, поэтому и понадобились защищенные элементы.

Одно из преимуществ инкапсуляции в том, что она позволяет разработчику класса проверить правильность любых значений, присваиваемых переменным-членам, и тем самым предотвратить ошибки программирования.

Другое преимущество управления доступом к внутренним структурам данных заключается в том, что автор класса может свободно изменить способ представления этих данных, не изменяя другие части программы, использующие класс (до тех пор, пока сохраняется интерфейс вызовов общедоступных функций-членов).

Таким образом, умелое использование уровней доступа повышает надежность программ и их способность к изменениям, ослабляя взаимозависимость между объектами. Правильно описанными функциями-элементами типа public можно изменять закрытые элементы, не затрагивая программный код других объектов. В реальной жизни мы подобным образом взаимодействуем с различными предметами: телевизором, будильником, радиоприемником, автомобилем. Знать внутреннее устройство их нам необязательно, однако нам важны внешние кнопки и ручки управления изделия.

Определение класса включает две части:

1) заголовок класса, состоящий из ключе­вого слова class и имени класса;

2) тело класса, заключенное в фи­гурные скобки и заканчивающееся точкой с запятой.

В качестве примера, приведем класс Stack, созданный на основе предыдущих ей структуры и функций, реализующей свойство инкапсуляции.

Пример 2

// Defines the entry point for the console application.

#include "stdafx.h"

#include<string.h>

#include <iostream.h>

const int MAXSIZE = 20;

const char * msg[ ] = { "Переполнение стекаn","Стек пустn "};

enum boolean { FALSE, TRUE };

class Stack

{

private:

char s[MAXSIZE];

int top;

public:

void Err_rep(int e_num) { cout << msg[e_num]; } // Сообщение об ошибке

void Reset() { top = 0; }                                             // Очистить стек

boolean Push(char c)         // Поместить символ в стек

{

if (top == MAXSIZE-1)

{        

err_rep(0);

return FALSE;

}

s[top++] = c;

return TRUE;

}

char Pop()                    // извлечь символ из стека

{   

f (top == 0)

{

err_rep(1);

return FALSE;

}

return (s[—top]);

}

};

int main(int argc, char* argv[ ])

{

char * ptr="stroka simvolov";

Stack q;

q.Reset();

for (int i=0; i< strlen(ptr); i++) q.Push(*(ptr+i));

for (i=0; i< strlen(ptr); i++) cout<<q.Pop();

cout<<endl;

return 0;

}

Следует обратить внимание на закрытые и общедоступные переменные и функции, а также на доступ к ним функций-членов, объединенных в одну «капсулу» – класс.