Программирование >>  Инициализация объектов класса, структура 

1 ... 238 239 240 [ 241 ] 242 243 244 ... 395


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 должен присутствовать



1 ... 238 239 240 [ 241 ] 242 243 244 ... 395

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика