
5. Переопределение операций.
Существуют средства, которые позволяют переопределять уже существующие операции. Такое переопределение называют перегрузкой операций. Т.о., при необходимости одна и та же операция помимо основной, предопределенной в языке семантики, может иметь в программе, или даже в иерархии составных типов несколько дополнительных семантик. Для определения операции используется вводимая пользователем функция с ключевым словом operator, за которым следует символ операции.
Общие правила переопределения операций:
За исключением операций new и delete, операции должны быть не статическими функциями-элементами класса или иметь минимум один аргумент типа класса. Функции-операции =, (), [], -> должны быть нестатическими элементами класса.
!!!! Нестатические элементы-функции класса ассоциируются с конкретным объектом, поэтому при доступе к элементам-данным в таких функциях имя объекта или вовсе не указывается или заменяется словом this. В статические элементы-функции объект необходимо передавать как параметр и указывать его имя при доступе к нестатическим элеметам-данным. Для нестатических элементов-данных их копия существует для каждого объекта класса. Для статических – такая копия только одна, и доступ к ней осуществляется без конкретной ссылки на объект класса.
Функция operator@() рассматривается как префиксная форма оператора, функция operator@(int) соответствует постфиксной форме, параметр функции является фиктивным.
Операция, которая переопределяется, должна существовать в языке.
Нельзя переопределять операции: ., ::, ?:.
Приоритет операций при переопределении сохраняется.
При переопределении любой унарной операции @, выражение @х или х@ интерпретируется как x.operator@() или operator@(x). Для любой бинарной операции @ выражение х@y интерпретируется как x.operator@(y) или operator@(x,y).
Операции new и delete могут быть переопределены. Операция new должна возвращать результат типа void* и иметь первый аргумент типа size_t. Операция delete должна возвращать результат типа void и иметь первый аргумент типа *void, второй аргумент может быть типа size_t. Операции new и delete всегда являются статическими элементами класса, даже при присутствии в их описании ключевого слова static.
Для задания новой семантики операции @ нужно выполнить следующие действия:
Включит в соответствующий составной тип описание функции с именем operator@.
Включит в этот же тип описания функций для выполнения необходимых преобразований типов.
Дать внешнее определение для функции operator@.
Дать внешние определения для всех функций преобразований ттипов.
6. Абстрактные и реализуемые классы.
Виртуальные функции позволяют классам-наследникам определять различные версии функций базового класса.
«Чистые» виртуальные функции – виртуальные функции, не имеющие реализации, их код не существует.
Абстрактный класс –класс, имеющий по крайней мере одну «чистую» виртуальную функцию. Он используется только как базовый для других классов, создавать объекты такого класса нельзя. Он имеет конструкторы и деструкторы. Абстрактный класс не может быть типом аргумента функции или возвращаемого значения. Однако можно описывать указатели и ссылки на такой класс. Классы, порождаемые от абстрактного, рассматриваются как его уточнение.
Класс, производный от абстрактного, может обеспечить тело, определяющее порожденную «чистую» виртуальную функцию. Если он не делает этого, то производный класс остается абстрактным, обеспечивая тем самым базу для дальнейших производных. Когда будет достигнут производный класс, в котором нет чистых виртуальных функций, этот класс будет называться неабстрактным классом, или реализуемым классом. Эти классы могут быть использованы для получения полезных объектов.
Абстрактный класс может быть базовым как для абстрактного класса, так и для реализуемого.