Дружественные функции

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

class className

(1

public: ~

className(); // Конструктор по умолчанию // Другие конструкторы friend returnType friendFunction(<список параметров>) ;

};

Листинг 3.12. Объявление дружественных функций.

Если обычные функции-члены имеют автоматический доступ ко всем данным своего класса за счет передачи скрытого параметра - указателяthis на экземпляр класса, то дружественные функции требуют явной спецификации этого параметра. Действительно, объявленная в классе Х дружественная функция F не принадлежит этому классу, а, значит, не может быть вызвана операторами х. F и xptr->F (где х- экземпляр класса X, a xptr- его указатель). Синтаксически корректными будут обращения F (& х) или F (xpt r).

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

3.6 Новые возможности языка C++

C++Builder обеспечивает не только поддержку последних нововведении стандарта ANSI C++, но и расширяет язык новыми возможностями. Компоненты, свойства, методы, обработчики событии, а также шаблоны, пространства имен, явные и непостоянные объявления, RTTI и исключения - вся мощь этих средств доступна программистам, использующим C++Builder для визуальной разработки приложений.

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

Некоторые из расширений (например, _classid) C++Builder резервирует, главным образом, для внутреннего использования. Другие расширения совершенно очевидны (_int8, _intl6 и т.д.), и здесь не рассматриваются. Наше внимание будет сфокусировано на наиболее значимых расширениях C++, которые, в основном, относятся к компонентным классам и будут постоянно встречаться как в тексте книги, так и в ваших приложениях, разрабатываемых в среде C++Builder.

3.6.1 Компоненты

Компоненты часто достигают более высокой степени инкапсуляции, нежели стандартные C++ классы. Проиллюстрируем это на простом примере разработки диалога, содержащего кнопку. В типичной C++ программе для Windows нажатие мышью на кнопку приводит к генерации сообщения WM_LBUTTONDOWN. Это сообщение должно быть "поймано" программой либо в оператореswitch, либо в соответствующей строке таблицы откликов (RESPONSE_TABLE), а затем передано процедуре реакции на это сообщение. Так, приложение, написанное в рамках OWL (Object Windows Library), использует макрос

DEFINE_RESPONSE_TABLE1(TEventTestDlgClient, TDialog)

//({TEventTestDlgClientRSP_TBL_BEGIN}}

EV_BN_CLICKED(IDEVENTBUTTON, EventBNClicked),

//({TEventTestDlgClientRSP_TBL_END}}

END_RESPONSE_TABLE;

чтобы ассоциировать событие (сообщение WM_LBUTTONDOWN), генерируемое кнопкой IDEVENTBUTTON в диалоге TEventTestDlgClient, с функцией реакции EventBNClicked.

C++Builder покончил с этими трудно осваиваемыми программистскими трюками. Компонента кнопки уже запрограммирована так, чтобы реагировать на нажатие кнопки событием OnClick. Все, что надо сделать - это выбрать готовый (или написать собственный) метод и с помощью Инспектора объектов включить его в обработчик данного события.