Файл: Pobegaylo_A._C_Cplus_dlya_studenta.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 13.12.2020

Просмотров: 4292

Скачиваний: 28

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Глава 14. Классы 

181 

  if (box.isEmpty()) 
    box.put(10); 
  if (!box.isEmpty()) 
    n = box.get(); 
 
  cout << n << endl;   // печатает 10 
 
  return 0; 

14.4. Указатель 

this

 

По умолчанию каждая не статическая функция-член класса имеет 
доступ к указателю с именем 

this

, который указывает на объект, 

для которого эта функция вызвана. Здесь 

this

 является ключевым 

словом языка программирования С++. Можно сказать, что указа-
тель 

this

  является  неявным  параметром  каждой  функции-члена 

класса. Указатель 

this

 имеет следующий тип: 

  имя_класса* const 

В принципе к любому члену класса, принадлежащему текущему 
объекту,  можно  обратиться  через  указатель 

this

.  Например,  в 

функции-члене класса 

IntBox

 можно написать так: 

  this -> empty = false; 

Но,  т. к.  функции-члены  класса  имеют  доступ  ко  всем  членам 
класса по умолчанию, то указатель 

this

 используется в основном 

для возврата указателя или ссылки на объект, к которому приме-
няется функция-член класса. 

14.5. Спецификаторы доступа 
к членам класса 

Для ограничения доступа к членам класса вне его области види-
мости используются спецификаторы доступа: 

public

protected

 и 

private

,  которые  также  называются 

метками

  и  могут  использо-

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


background image

Часть II. Язык программирования С++ 

182 

Все  члены  класса,  объявленные  после  метки 

public

  и  располо-

женные  до  следующей  метки,  доступны  как  в  классе,  так  извне 

класса. 
Все  члены  класса,  объявленные  после  метки 

protected

  и  распо-

ложенные до следующей метки, доступны только внутри класса и 

внутри потомков класса. 
Все  члены  класса,  объявленные  после  метки 

private

  и  располо-

женные до следующей метки, доступны только внутри класса. 
По  умолчанию  все  члены  класса,  объявленные  после  ключевого 
слова 

class

  до  первой  метки,  имеют  спецификацию  доступа 

private

, а объявленные после ключевых слов 

struct

 или 

union

 до 

первой метки — спецификацию доступа 

public

Чтобы  запретить  пользователям  доступ  к  атрибутам  класса 

IntBox

, этот класс должен быть определен следующим образом: 

  class IntBox 
  { 
    bool empty;  // состояние контейнера 
    int  room;   // место для хранения целого числа 
  public: 
    IntBox();         // конструктор 
    void put(int n);  // положить целое число в контейнер 
    int  get();       // взять целое число из контейнера 
    bool isEmpty();   // проверить, свободно ли место 
  }; 

Как видим, в этом случае клиенты класса имеют доступ к атрибу-

там класса только через методы этого класса или, как еще гово-

рят,  через  интерфейс  класса.  Такой  подход  к  проектированию 

структуры  класса  называется 

инкапсуляцией

.  Но  в  этом  случае 

возникает  проблема  инициализации  атрибута 

empty

  при  опреде-

лении  объекта  класса.  Для  этого  используются  специальные 

функции-члены  класса,  которые  называются 

конструкторами

.  

В  нашем  случае  это  функция 

IntBox

,  которая  имеет  следующее 

определение: 

  IntBox::IntBox() { empty = true; } 

Более  подробно  конструкторы  классов  будут  рассмотрены  в 

гл. 15


background image

Глава 14. Классы 

183 

14.6. Друзья класса 

При  работе  с  классами  может  возникнуть  следующая  проблема. 
Допустим,  что  класс  с  закрытыми  атрибутами  определяет  тип 
параметра  функции.  Возможна  такая  ситуация,  что  эта  функция 
не может быть реализована, т. к. она не имеет доступа к атрибу-
там экземпляра класса. Чтобы разрешить эту проблему, функция 
должна быть объявлена как друг класса. 
Второй причиной при определении друзей класса является жела-
ние  реализовать  более  быстрые  функции,  которые  не  являются 
членами класса, но работают с атрибутами этого класса. Очевид-
но,  что  прямой  доступ  к атрибутам  класса будет  работать  быст-
рее, чем доступ к этим же атрибутам через функции-члены класса. 

 

Отношение  дружбы  нарушает  принцип  инкапсуляции  в  объектно-
ориентированном программировании. Поэтому друзей класса нуж-
но выбирать осторожно. 

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

friend

 и мо-

жет  встречаться  только  внутри  определения  класса.  Так  как  
друзья класса не являются членами класса, то не имеет значения 
после  какой  из  меток  они  объявлены.  Друзьями  класса  могут 
быть объявлены как функции из пространства имен, так и функ-
ции-члены другого класса. 
Определяются  функции-друзья  класса  как  обычные  функции 
внутри или вне класса. Если функция определяется внутри клас-
са,  то  это  определение  одновременно  является  и  объявлением 
функции. В этом случае имя функции принадлежит тому же про-
странству имен, что и имя класса. Если функция друг класса оп-
ределяется вне класса, то при этом ключевое слово 

friend

 не ис-

пользуется. 
Например,  объявим  для  класса 

IntBox

  две  дружественные  функ-

ции: 

in

  и 

out

, которые соответственно предназначены для ввода 

целого числа в контейнер с консоли и для вывода целого числа из 


background image

Часть II. Язык программирования С++ 

184 

контейнера  на  консоль.  Тогда  определение  класса 

IntBox

  будет 

выглядеть следующим образом: 

  class IntBox 
  { 
    bool empty;  // состояние контейнера 
    int  room;   // место для хранения целого числа 
  public: 
    IntBox();         // конструктор 
    void put(int n);  // положить целое число в контейнер 
    int  get();       // взять целое число из контейнера 
    bool isEmpty();   // проверить, свободно ли место 
    friend void in(IntBox& box);   // ввод числа с консоли 
    friend void out(IntBox& box);  // вывод числа на консоль 
  }; 

Реализацию этих функций можно поместить как в исходный файл 
IntBox.cpp, так и в новый исходный файл. Выберем второй вари-
ант  и  создадим  исходный  файл  InOutBox.cpp.  В  листинге  14.4 
приведен текст этого файла. 

Листинг 14.4. Реализация функций-друзей класса 

#include "IntBox.h" 
#include <iostream> 
using namespace std; 
 
void in(IntBox& box) 

  cin >> box.room; 
  box.empty = false; 

void out(IntBox& box) 

  cout << box.room; 
  box.empty = true; 

В листинге 14.5 показано, как использовать эти функции для вво-
да целого числа с консоли в контейнер и вывода этого же целого 
числа на консоль из контейнера. 


background image

Глава 14. Классы 

185 

Листинг 14.5. Использование функций-друзей класса 

#include "IntBox.h" 
#include <iostream> 
using namespace std; 
int main() 

  IntBox box; 
 
  cout << "Input integer: "; 
  in(box); 
  out(box); 
  cout << endl; 
 
  return 0; 

Друзьями  класса  могут  быть  также  объявлены  другие  классы.  
В этом случае доступ к закрытым членам класса допускается для 
всех функций друга этого класса. Например, объявим для класса 

IntBox

  дружественный  класс 

PrintBox

,  который  содержит  функ-

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

IntBox

  бу-

дет выглядеть следующим образом: 

  class IntBox 
  { 
    bool empty;  // состояние контейнера 
    int  room;   // место для хранения целого числа 
  public: 
    IntBox();         // конструктор 
    void put(int n);  // положить целое число в контейнер 
    int  get();       // взять целое число из контейнера 
    bool isEmpty();   // проверить, свободно ли место 
 
    friend void in(IntBox& box);   // ввод числа с консоли 
    friend void out(IntBox& box);  // вывод числа на консоль 
 
    friend struct PrintBox;  // печать содержимого контейнера 
  }; 


Смотрите также файлы