Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++.docx
Скачиваний:
74
Добавлен:
29.02.2016
Размер:
240.89 Кб
Скачать

6.3. Дружественные классы и функции

В рассмотренных примерах наследования функция Draw() дочерних классов использует переменные sp_x, sp_y, ep_x, ep_y, width и color базовых классов, которые необходимо было объявлять в разделе protected. Вместе с тем лучшую защиту этих переменных можно обеспечить, объявив их частными (private). Но тогда при наследовании они оказываются недоступными в производных классах, а реализация функции Draw() невозможной. Чтобы разрешить эту проблему, дочерние классы, использующие частные переменные базовых классов, необходимо объявить как дружественные к соответствующим базовым.

Для объявления дружественного класса используется ключевое слово friend, за которым следует имя класса. Следующий пример демонстрирует объявление дружественного класса CLine классам CPos и CProp:

class CLine; //идентификатор класса class CPos { protected: CPos() {} CPos(int x1, int y1, int x2, int y2) {SetParam(x1,y1,x2,y2);} ~CPos() {} public: friend CLine; //объявление дружественного класса void SetParam(int x1, int y1, int x2, int y2); protected: int sp_x, sp_y; int ep_x, ep_y; }; class CProp { protected: CProp() {} CProp(int wdt, int clr) {SetProperty(wdt,clr);} ~CProp(); public: friend CLine; //объявление дружественного класса void SetProperty(int wdt, int clr); protected: int width, color; };

В данном примере класс CLine является производным от классов CPos и CProp, поэтому он объявляется после них. Однако, чтобы сделать класс CLine дружественным базовым классам он должен быть объявлен до них, иначе компилятор С++ выдаст синтаксическую ошибку. Чтобы разрешить эту проблему язык С++ допускает использование идентификатора класса, который говорит компилятору о том, что такой класс есть, но его описание будет дано ниже. Благодаря этому удается организовать перекрестные ссылки между классами, стоящие на разных уровнях иерархии. В результате такой организации частные элементы sp_x, sp_y, ep_x, ep_y, width и color классов CPos и CProp оказываются доступными только одному производному классу CLine и никакому другому, что обеспечивает их лучшую защиту по сравнению с уровнем доступа protected.

Дружественными можно объявлять не только классы, но и отдельные функции классов. Например, для класса CLine важно, чтобы переменные sp_x, sp_y, ep_x, ep_y, width и color были доступны только функции Draw(). Поэтому было бы целесообразно ее и сделать дружественной, а не весь класс целиком. Однако для этого потребовалось бы ее прототип описать до классов CPos и CProp, что сделать в данном случае невозможно, т.к. класс CLine, в котором находится функция Draw(), описан в последнюю очередь. Но, в общем, дружественные функции можно задавать, как показано в следующем фрагменте программы:

class CPos; class CLine { public: CLine() {} ~CLine() {} void Draw(CPos* pos); }; class CPos { public: CPos() {} ~CPos() {} friend void CLine::Draw(CPos* pos); private: int sp_x, sp_y; int ep_x, ep_y; }; void CLine::Draw(CPos* pos) { MoveTo(pos->sp_x, pos->sp_y); LineTo(pos->ep_x, pos->ep_y); }

Особенностью организации классов CLine и CPos является то, что функция Draw() класса CLine использует в качестве аргумента указатель на класс CPos, который объявлен ниже. Поэтому реализации функции Draw() должна быть объявлена после определения класса CPos, иначе компилятор С++ выдаст сообщение об ошибке. Благодаря тому, что функция Draw() является дружественной классу CPos, она может получать доступ к частным элементам этого класса через переданный ей указатель.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]