Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOP.doc
Скачиваний:
7
Добавлен:
25.04.2019
Размер:
1.34 Mб
Скачать

Delete[] __thematrix;

}

1.4. Обращение к компонентам объектов

Работа с объектом – это, прежде всего, вызов компонентных функций, объявленных в его классе (обращение к компонентным функциям). В общем случае такой вызов называют передачей объекту сообщения. Те действия, которые выполняет функция, называются реакцией объекта на сообщение. Реакцией может быть отправка сообщения другому объекту, изменение состояния объекта, возврат текущего состояния объекта и др. В принципе, возможно и обращение к данным объекта, однако это считается исключением ввиду ослабления уровня инкапсуляции; все данные, как правило, делают недоступными и обращение к ним стремятся реализовать через соответствующие компонентные функции.

Обратиться к компоненту объекта можно несколькими способами: через уточнение имени компонента, путем косвенного выбора, через указатель на компонент.

Формат доступа к компоненту через его сокращенное квалифицированное имя (уточнение имени) следующий:

object_id.member_id // для данных

object_id.member_function_id(arguments) // для функций

где object_id – имя объекта, а member_id (member_function_id) – имя компонента (arguments – список аргументов компонентной функции).

Доступ через полное квалифицированное имя компонента строится аналогично, но включает имя класса class_id и имеет формат:

object_id.class_id::member_id // для данных

object_id.class_id::member_function_id(arguments) // для функций

Следует отметить, что такой формат используется достаточно редко, в частности, в случае множественного наследования, когда есть неоднозначность при обращении к компонентам без явной квалификации их имени (более подробно см. ниже).

Косвенный выбор компонента становится возможным после определения указателя на объект. Записывается косвенный выбор через операцию –> и имеет формат вида:

pointer_to_object–>member_id // для данных

pointer_to_object–>member_function_id(arguments) // для функций

где pointer_to_object – указатель на объект.

Допускаются и обращения с разыменованием указателя:

(*pointer_to_object).member_id // для данных

(*pointer_to_object).member_function_id(arguments) // для функций

а также с полным квалифицированным именем:

pointer_to_object–>class_id::member_id // для данных

pointer_to_object–>class_id::member_function_id(arguments) // для функций

(*pointer_to_object).class_id::member_id // для данных

(*pointer_to_object).class_id::member_function_id(arguments) // для функций

В приведенном ниже фрагменте кода используются оба описанных способа обращения к компонентам (по комментариям можно легко понять сущность каждого оператора).

CBitSequence seq; // создание двоичной последовательности

// ввод значений последовательности

seq.input(0); // нулевое значение

seq.input(1); // первое значение

...

seq.print(); // печать последовательности

CBitSequence * pseq = &seq; // указатель на объект

// снова ввод значений

pseq->input(3); // косвенный выбор

pseq->input(4);

pseq->print(); // печать после модификации

(*pseq).input_all(); // уточнение имени с разыменованием указателя

(*pseq).print();

...

Эскиз определения класса CBitSequence представлен ниже (определение класса, безусловно, далеко от «совершенства», но для понимания способов доступа к компонентам объектов вполне достаточно).

class CBitSequence {

public:

// конструкторы

explicit CBitSequence(int len);

CBitSequence(const CBitSequence &);

// деструктор

~CBitSequence() { delete[] __items; }

void print();// печать последовательности

void input(int index); // ввод элемента с заданным индексом

void input_all(void); // ввод всех элементов сразу

private:

bool * __items;

const int __len;

};

Существует еще один способ обращения к компонентам объектов – через указатели на компоненты. Указатель на компонент класса – особый вид указателей, который можно «привязать» к компоненту класса с заданным форматом (прототипом). Значением такого указателя является «связь» с компонентом класса4. Указатель на компонент можно определить согласно следующему обобщенному формату:

value_type (class_id::*pointer_id) initializer // для данных

value_type (class_id::*pointer_id) (parameters) initializer // для функций,

где value_type – тип компонента (для компонентной функции – тип возвращаемого значения); class_id – имя класса, pointer_id – имя указателя на компонент; initializer – инициализирующее выражение; parameters – список параметров компонентной функции. Формат инициализатора имеет вид

= &class_id::member_id,

где member_id – имя некоторого компонента класса, формат которого удовлетворяет определению указателя на компонент.

Обращение к компоненту объекта через указатель на компонент реализуется операциями .* и –>*. Обе эти операции бинарные и в качестве правого операнда ожидают указатель на компонент. Левым операндом у первой из них должна быть ссылка на объект класса, а у второй – указатель на объект класса. Форматы обращения через указатели на компоненты будут следующими:

object_id.*pointer_id // для данных

object_id.*pointer_id(arguments) // для функций.

Если имеется указатель на объект (pointer_to_object), то обратиться к компонентам объекта можно так:

pointer_to_object–>*pointer_id // для данных

pointer_to_object->*pointer_id(arguments) // для функций

(*pointer_to_object).*pointer_id // для данных

(*pointer_to_object).*pointer_id(arguments) // для функций.

Теперь рассмотрим пример использования указателей на компоненты. В примере воспользуемся уже определенным выше классом CBitSequence, моделирующим двоичные последовательности.

Пример

...

CBitSequence seq; // создание двоичной последовательности

CBitSequence * pseq = &seq; // указатель на объект

...

// указатель на функцию CBitSequence::input

void (CBitSequence::*pmember) (int) = &CBitSequence::input;

(seq.*pmember)(5); // ввод компонента

(pseq->*pmember)(6); // ввод компонента

// указатель на функцию CBitSequence::print

void (CBitSequence::*panothermember) () = &CBitSequence::print;

(seq.*panothermember)(); // печать последовательности

(pseq->*panothermember)(); // печать последовательности

...

Необходимо отметить, что указатели на компоненты жестко типизированы и даже при незначительном отличии являются несовместимыми. В нашем примере указатели pmember и panothermember отличаются только лишь одним декларатором параметра (у первого параметр типа int, у второго параметров нет). Тем не менее этого достаточно для их несовместимости. Преобразовать указатель на компонент к новому типу можно с помощью операции reinterpret_cast.

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