|
Программирование >> Инициализация объектов класса, структура
class absInt { public: int operator()( int val ) { int result = val < 0 ? -val : val; return result; можно определить класс absInt: Перегруженный оператор operator() должен быть объявлен как функция-член с произвольным числом параметров. Параметры и возвращаемое значение могут иметь любые типы, допустимые для функций (см. разделы 7.2, 7.3 и 7.4). operator() вызывается путем применения списка аргументов к объекту того класса, в котором он определен. Мы рассмотрим, как он используется в одном из обобщенных алгоритмов, описанных в главе 12. В следующем примере обобщенный алгоритм transform() вызывается для применения определенной в absInt операции к каждому элементу #include <vector> #include <algoritm> int main() { int ia[] = { -0, 1, -1, -2, 3, 5, -5, 8 }; vector< int > ivec( ia, ia+8 ); заменить кажд элемент его абсотн значением transform( ivec.begin(), ivec.end(), ivec.begin(), absInt() ); ... вектора ivec, т.е. для замены элемента его абсолютным значением. Первый и второй аргументы transform() ограничивают диапазон элементов, к которым применяется операция absInt. Третий указывает на начало вектора, где будет сохранен результат применения операции. Четвертый аргумент - это временный объект класса absInt, создаваемый с помощью конструктора по умолчанию. Конкретизация обобщенного алгоритма transform() , вызываемого из main() , могла бы выглядеть так: строки, на которую ссылается string. (Возбуждение и обработка исключений обсуждались в главе 11.) 15.5. Оператор вызова функции Оператор вызова функции может быть перегружен для объектов типа класса. (Мы уже видели, как он используется, при рассмотрении объектов-функций в разделе 12.3.) Если определен класс, представляющий некоторую операцию, то для ее вызова перегружается соответствующий оператор. Например, для взятия абсолютного значения числа типа int typedef vector< int >::iterator iter type; конкретизация transform() операция absInt применяется к элементу вектора int iter type transform( iter type iter, iter type last, iter type result, absInt func ) while ( iter != last ) *result++ = func( *iter++ ); вызается absInt::operator() return iter; func - это объект класса, который предоставляет операцию absInt, заменяющую число типа int его абсолютным значением. Он используется для вызова перегруженного оператора operator() класса absInt. Этому оператору передается аргумент *iter, указывающий на тот элемент вектора, для которого мы хотим получить абсолютное значение. 15.6. Оператор стрелка Оператор стрелка , разрешающий доступ к членам, может перегружаться для объектов класса. Он должен быть определен как функция-член и обеспечивать семантику указателя. Чаще всего этот оператор используется в классах, которые предоставляют интеллектуальный указатель (smart pointer), ведущий себя аналогично встроенным, но поддерживают и некоторую дополнительную функциональность. Допустим, мы хотим определить тип класса для представления указателя на объект class ScreenPtr { ... private: Screen *ptr; Screen (см. главу 13): }; Определение ScreenPtr должно быть таким, чтобы объект этого класса гарантировано указывал на объект Screen: в отличие от встроенного указателя, он не может быть нулевым. Тогда приложение сможет пользоваться объектами тина ScreenPtr, не проверяя, указывают ли они на какой-нибудь объект Screen. Для этого нужно определить класс ScreenPtr с конструктором, но без конструктора по умолчанию class ScreenPtr { public: ScreenPtr( const Screen ss ) : ptr( ss ) { } ... (детально конструкторы рассматривались в разделе 14.2): ScreenPtr p1; ошибка: у класса ScreenPtr нет конструктора по умолчанию Screen myScreen( 4, 4 ); инициализатор - объект класса Screen, на который будет ссылаться объект ScreenPtr: ScreenPtr ps( myScreen ); правильно Чтобы класс ScreenPtr вел себя как встроенный указатель, необходимо определить некоторые перегруженные операторы - разыменования (*) и стрелку для доступа к перегруженные операторы для поддержки поведения указателя class ScreenPtr { public: Ca v-a Screens operator*() { return *ptr; } Screen* operator->() { return ptr; } членам: }; Оператор доступа к членам унарный, поэтому параметры ему не передаются. При использовании в составе выражения его результат зависит только от типа левого операнда. Например, в инструкции point->action(); исследуется тип point. Если это указатель на некоторый тип класса, то применяется семантика встроенного оператора доступа к члену. Если же это объект или ссылка на объект, то проверяется, есть ли в этом классе перегруженный оператор доступа. Когда перегруженный оператор стрелка определен, он вызывается для объекта point, иначе инструкция неверна, поскольку для обращения к членам самого объекта (в том числе по ссылке) следует использовать оператор точка . Перегруженный оператор стрелка должен возвращать либо указатель на тип класса, либо объект класса, в котором он определен. Если возвращается указатель, то к нему применяется семантика встроенного оператора стрелка . В противном случае процесс продолжается рекурсивно, пока не будет получен указатель или определена ошибка. Например, так можно воспользоваться объектом ps класса ScreenPtr для доступа к членам Screen: ps->move( 2, 3 ); Поскольку слева от оператора стрелка находится объект типа ScreenPtr, то употребляется перегруженный оператор этого класса, который возвращает указатель на объект Screen. Затем к полученному значению применяется встроенный оператор стрелка для вызова функции-члена move() . Ниже приводится небольшая программа для тестирования класса ScreenPtr. Объект типа ScreenPtr используется точно так же, как любой объект типа Screen*: В любом определении объекта класса ScreenPtr должен присутствовать
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |