Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

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

Три спецификатора доступа обеспечивают в C++ управление доступом. Эти спецификаторы являются основанием принципа инкапсуляции - одного из трёх основных принципов объектно-ориентированного программирования. Соблюдение правил доступа повышает надёжность программного обеспечения.

Спецификаторы доступа способны обеспечить многоуровневую защиту функций и данных в наследуемых классах. Порождаемые на основе "инкапсулированных" классов объекты способны поддерживать жёсткий интерфейс. Они подобны "чёрным" ящикам с чётко обозначенными входами и выходами. Вместе с тем, следует признать, что система управления доступом, реализованная на основе трёх спецификаторов, не является гибкой. С её помощью может быть реализована защита по принципу "допускать ВСЕХ (члены класса, объявленные в секции public) или не допускать НИКОГО (члены класса, объявленные в секциях protected и private)". В C++ существует возможность организации более гибкой защиты. Здесь можно также объявлять функции, отдельные функции-члены классов и даже классы (в этом случае речь идёт о полном множестве функций-членов класса), которые получают доступ к защищённым и приватным членам данного класса. Что означает реализацию системы управления доступом принципу "не допускать НИКОГО, КРОМЕ". Такие функции и классы называют дружественными функциями и классами. Объявление дружественных классов и функций включается в объявление данного класса вместе со спецификатором объявления friend. Здесь нам потребуется всего одна форма Бэкуса-Наура для того, чтобы дополнить синтаксис объявления.

СпецификаторОбъявления ::= friend
                       ::= *****

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

#include <iostream.h>
class XXX; 
/*
Неполное объявление класса. Оно необходимо для объявления типа
параметра функции-члена для следующего класса.
*/
class MMM
{
 private:
  int m1;
 public:
  MMM(int val);
  void TypeVal(char *ObjectName, XXX& ClassParam);
};
MMM::MMM(int val)
{
 m1 = val;
}
/*
Определение функции-члена TypeVal располагается после объявления
класса XXX. Только тогда транслятор узнаёт о структуре класса, к
которому должна получить доступ функция MMM::TypeVal.
*/
class XXX
{
 friend class YYY;
 friend void MMM::TypeVal(char *ObjectName, XXX& ClassParam);
 friend void TypeVal(XXX& ClassParamX, YYY& ClassParamY);
/*
В классе объявляются три друга данного класса: класс YYY, функция-член
класса MMM, простая функция TypeVal. В класс XXX включаются лишь
объявления дружественных функций и классов. Все определения
располагаются в других местах - там, где им и положено быть - в своих
собственных областях видимости.
*/
 private:
  int x1;
 public:
  XXX(int val);
};
XXX::XXX(int val)
{
 x1 = val;
}
void MMM::TypeVal(char *ObjectName, XXX& ClassParam)
{
 cout << "Значение " << ObjectName << ": " << ClassParam.x1 << endl;
}
/*
Отложенное определение функции-члена MMM::TypeVal.
*/
class YYY
{
 friend void TypeVal(XXX& ClassParamX, YYY& ClassParamY);
 private:
  int y1;
 public:
  YYY(int val);
  void TypeVal(char *ObjectName, XXX& ClassParam);
};
YYY::YYY(int val)
{
 y1 = val;
}
void YYY::TypeVal(char *ObjectName, XXX& ClassParam)
{
 cout << "Значение " << ObjectName << ": " << ClassParam.x1 << endl;
}
void TypeVal(XXX& ClassParamX, YYY& ClassParamY);
void main()
{
 XXX mem1(1);
 XXX mem2(2);
 XXX mem3(3);
 YYY disp1(1);
 YYY disp2(2);
 MMM special(0);
 disp1.TypeVal("mem1", mem1);
 disp2.TypeVal("mem2", mem2);
 disp2.TypeVal("mem3", mem3);
 special.TypeVal("\n mem2 from special spy:", mem2);
 TypeVal(mem1, disp2);
 TypeVal(mem2, disp1);
}
void TypeVal(XXX& ClassParamX, YYY& ClassParamY)
{
 cout << endl;
 cout << "???.x1 == " << ClassParamX.x1 << endl;
 cout << "???.y1 == " << ClassParamY.y1 << endl;
}

В этом примере все функции имеют одинаковые имена. Это не страшно. Это даже полезно, поскольку становится очевидным факт существования разных областей действия имён.

В заключение раздела перечислим основные правила пользования новыми средствами управления доступа - дружественной системой защиты.

  • Друзья класса не являются членами класса. Они должны определяться вне класса, для которого они объявляются друзьями, а об особых отношениях между ними и данным классом свидетельствует лишь специальное объявление(!) со спецификатором объявления friend. Объявления дружественного класса означает, что в дружественном классе доступны все компоненты объявляемого класса.
  • Дружественные данному классу функции не являются членами этого класса. Поэтому они не могут быть вызваны из объекта-представителя класса, для которого была объявлена другом данная функция, при помощи операции доступа к члену класса.
  • Дружественная функция может быть функцией-членом другого ранее объявленного класса. Правда, при этом само определение дружественной функции приходится располагать после объявления класса, другом которого была объявлена данная функция. Это не очень удобно и красиво, но зато работает.
  • Дружественная функция не имеет this указателя для работы с классом, содержащим её объявление в качестве дружественной функции. Дружба - это всего лишь дополнение принципа инкапсуляции и ничего более.
  • Дружественные отношения не наследуются. Дружественные функции не имеют доступа к членам производного класса, чьи базовые классы содержали объявления этих функций. Дети не отвечают за отношения своих родителей.

Назад | Содержание | Вперед

 

VPS в 21 локации

От 104 рублей в месяц

Безлимитный трафик. Защита от ДДоС.

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...