
- •6Vpj7-h3cxh-hbtpt-x4t74-3yvy7
- •Оглавление
- •Предисловие
- •Введение
- •1.1. Понятие класса и объекта. Инкапсуляция
- •1.2. Определение классов. Компоненты. Доступность
- •Class_key /*class_id*/ { /*members_list*/ };
- •Value_type class_id::function_id(parameters) {statements}
- •CPoint point1(100,70); // локальный объект
- •Static cPoint point3(50,120); // статический объект
- •Class_id(parameters) /*:initializer_list*/ {/*statements*/}
- •CString(const char *);
- •Delete[] __thematrix;
- •1.4. Обращение к компонентам объектов
- •1.5. Статические и нестатические компоненты классов
- •1.7. Указатель this
- •В опросы для самопроверки
- •2. Механизм наследования. Полиморфизм
- •2.1. Формы наследования. Базовые и производные классы
- •Class_key class_id: inheritance_specifier base_class_id {member_list};
- •2.3. Абстрактные классы
- •2.4. Множественное наследование и виртуальные классы
- •2.5. Преобразование динамических типов. Динамическая идентификация типов
- •Catch ( std::bad_cast & ) { // обработка исключения
- •Return 0;
- •Вопросы для самопроверки
- •3. Дружественные функции и классы
- •3.1. Дружественные функции
- •3.2. Дружественные классы
- •Вопросы для самопроверки
- •4. Механизм вложения
- •4.1. Вложенные классы
- •4.2. Локальные классы
- •Вопросы для самопроверки
- •5. Объектная модель и шаблоны
- •5.1. Определение, описание и инстанцирование шаблонов
- •::Function_id(function_parameter_list) { statements }
- •5.2. Параметры и аргументы шаблонов
- •Class identifier typename identifier
- •// Key, Data – параметры-типы (типы ключа и данных отображения)
- •// Container – контейнер, где содержится информация отображения class сMap {
- •Class MyTemplate
- •Int array[10]; struct Structure { int m; static int sm; } str;
- •5.3. Шаблоны компонентных функций
- •Value_type function_template_id(function_parameter_list) { statements }
- •::Function_template_id(function_parameter_list) { statements }
- •5.4. Специализация шаблонов
- •Вопросы для самопроверки
- •6. Перегрузка операций
- •Value_type operator @ (parameter_list);
- •Value_type operator @ (parameter_list) { statements }
- •Return fail();
- •6.3. Перегрузка бинарных операций
- •Value_type operator @ (parameter); // компонентная функция
- •Value_type operator @ (parameter, parameter); // глобальная функция friend value_type operator @ (parameter, parameter); // дружественная функция
- •Return *this;
- •Return *this;
- •/* Присваиваем собственные данные класса d */
- •6.4. Перегрузка операций управления памятью
- •Typedef void (*new_handler) ();
- •Extern new_handler set_new_handler( new_handler new_p );
- •Void operator delete(void * memory) {
- •... // Специальная обработка пользователя ::operator delete(memory); // освободить память
- •Вопросы для самопроверки
- •7. Механизм исключений
- •Throw expression
- •7.3. Специальные средства поддержки механизма исключений
- •Unexpected_function set_unexpected(unexpected_function func_name);
- •Typedef void (* unexpected_function) ();
- •Extern char * __throwExceptionName; extern char * __throwFileName; extern unsigned __throwLineNumber;
- •Вопросы для самопроверки
- •8. Подсчет ссылок
- •8.1. Назначение механизма подсчета ссылок
- •8.2. Контекстно-независимая модель счетчика ссылок
- •8.4. Внедрение подсчета ссылок в существующий класс
- •Вопросы для самопроверки
- •9. Стандартная библиотека шаблонов (stl)
- •9.1. Назначение и архитектура stl
- •9.2. Последовательные контейнеры
- •Class vector {
- •// Определение итераторов
- •Sort(first,last); // сортировка вектора в диапазоне итераторов
- •Ifstream ifile ("example.In"); ofstream ofile ("example.Out");
- •OutputIterator copy(
- •InputIterator first, InputIterator last, OutputIterator result );
- •// Заполнение списка
- •Operator- (int)
- •Operator- (random access iterator) operator[] (int)
- •InputIterator find(InputIterator first, InputIterator last, const t & value);
- •InputIterator find(InputIterator first, InputIterator last, const t & value)
- •Return first;
- •OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
- •Return result;
- •OutputIterator transform (InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op)
- •Return result;
- •Void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
- •__Quick_sort_loop(first, last, comp); __final_insertion_sort(first, last, comp);
- •T accumulate(InputIterator first, InputIterator last, t init, Function f);
- •V.Push_back(2); V.Push_back(5);
- •9.5. Функторы
- •T operator()(const t & X) const { return -X; }
- •9.7. Адаптеры
- •S1.Push(1); s1.Push(5);
- •// Записать в вектор числа 1 2 3 4
- •// Сортировать по неубыванию
- •// Записать в вектор числа 4 6 10 3 13 2
- •Вопросы для самопроверки
- •Заключение
- •Библиографический Список
- •6Vpj7-h3cxh-hbtpt-x4t74-3yvy7
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.