Дружественные функции
Дружественные функции, хотя и не принадлежат какому-то классу, однако имеют доступ ко всем приватным и защищенным членам данных внешних классов. Листинг 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. Все, что надо сделать - это выбрать готовый (или написать собственный) метод и с помощью Инспектора объектов включить его в обработчик данного события.