|
Программирование >> Структурное программирование
Типичная ошибка программирования 8.6 Не предусматривают перегруженную операцию присваивания и конструктр копии для класса, когда объекты этого класса содержат указатели на динамически распределенную память. Замечание по технике программирования 8.4 Можно запретить присваивание одного объекта класса другому. Это делается путем определения операции присваивания как закрытого элемента класса. Замечание по технике программирования 8.5 Можно предохранить объекты класса от копирования; для этого просто делают закрытыми и перегруженную операцию присваивания, и конструктор копии. Строка int operator==(const Array &) const; проверка равенства объявляет перегруженную операцию проверки на равенство (==) для класса Array. Когда компилятор встречает в main выражение вида integersl == integers2 он активизирует функцию-элемент operator==, генерируя вызов integersl.operator==(integers2) Если элементы size массивов различны, функция-элемент operator== сразу возвращает О (ложь). В противном случае функция-элемент сравнивает каждую пару элементов. Если все они одинаковы, возвращается 1 (истина). Если обнаружилась первая пара различных элементов, это сразу же вызывает возврат О (ложь). Строка int operator!=(const Array &) const; сравнение на неравенство объявляет для класса перегруженную операцию проверки неравенства массивов. Функция-элемент operatorI= активизируется и работает аналогично перегруженной функции операции проверки равенства. Отметим, что перегруженная функция operator!= могла бы быть написана в терминах перегруженной функции operator== следующим образом: int Array::operator!=(const Array Sright) const { return !(*this == right);} Это определение функции использует перегруженную функцию орега-tor==, чтобы определить, равен ли один массив Array другому, а затем возвращает отрицание этого результата. Создание функции operator!= этим способом дает программисту возможность повторно использовать функцию operator== и уменьшить объем описания класса. Строка int Soperator[](int); операция индексации объявляет для класса перегруженную операцию индексации. Когда компилятор встречает в main выражение integersl[](5) он активизирует перегруженную функцию-элемент operator[], генерируя вызов integersl.operator[] (5) Функция-элемент operator[] проверяет, находится ли индекс в допустимом диапазоне, и если нет, то программа аварийно завершается. Если индекс в заданном диапазоне, то соответствуюш;ий элемент массива возвращ,ается как ссылка, так что он может быть использован как L-величина (например, с левой стороны оператора присваивания). Строка static int getArrayCountО; возвращение числа экземпляров объявляет статическую функцию-элемент getArrayCount, которая возвраш;ает значение статического элемента данных arrayCount, даже если не существует ни одного объекта класса Array. 8.9. Преобразования типов Большинство программ работает с информацией разных типов. Иногда все операции остаются в пределах одного типа . Например, сложение целого и целого дает снова целое (до тех пор, пока результат не станет слишком большим для представления целым). Но часто возникает необходимость преобразовать данные одного типа в данные другого типа. Это может случиться при присваиваниях, при вычислениях, при передаче значений функциям и возвращении значений от функций. Компилятор знает, как выполнить определенные преобразования между встроенными типами. Программист может регулировать преобразования встроенных типов путем приведения типов. Но что делать с типами, определенными пользователем? Компилятор не может сам по себе знать, как выполнять преобразования между встроенными типами и типами, определенными пользователем. Программист должен явно указать, как выполнять такие преобразования. Эти преобразования могут быть выполнены с помощью конструкторов преобразований - конструкторов с единственным аргументом, которые преобразуют объекты разных типов (включая встроенные типы) в объекты данного класса. Позже в этой главе мы используем конструктор преобразований, чтобы преобразовать обычные строки char* в объекты класса String. Операция преобразования (называемая также операцией приведения) может быть использована для преобразования объекта одного класса в объект другого класса или в объект встроенного типа. Такая операция преобразования должна быть нестатической функцией-элементом; операция преобразования этого вида не может быть дружественной функцией. Прототип функции А::operator char*() const; объявляет перегруженную функцию-операцию приведения для создания временного объекта char* из объекта определенного пользователем типа А. Перегруженная функция-операция приведения не указывает тип возвращаемых величин, потому что тип возвращаемых величин - это тип, к которому преобразован объект. Если s - объект класса, то когда компилятор встречает выражение (char*)s, он порождает вызов s.operator char*(). Операнд s - это объект класса s, для которого была активизирована функция-элемент operator char*. 8.10. Учебный пример: класс строка Краеугольным камнем изучения перегрузок операций явится построение нами класса, который управляет созданием и обработкой строк. C+-f- не имеет встроенного строкового типа данных. C-f-+ предоставляет нам возможность добавить в качестве класса наш собственный строковый тип и посредством механизма перегрузки обеспечить набор удобных операций для работы со строками. Различные части программы на рис. 8.5 включают заголовок класса, определения функций-элементов и программу драйвер для проверки нашего нового класса String. Сначала мы рассмотрим заголовок класса String и обсудим закрытые данные, использованные для представления объектов String. Затем мы пройдемся по открытому интерфейсу класса, обсуждая каждую из услуг, которые предоставляет наш класс. Далее мы рассмотрим программу драйвер в main. Мы обсудим желательный нам стиль кодирования, т.е. вид выражений, которые нам хотелось бы иметь возможность записывать для объектов нашего нового класса String, и соответствующий набор перегруженных операций класса. Затем мы обсудим определения функций-элементов класса String. Для каждой перегруженной операции мы рассмотрим код в программе драйвере, который активизирует перегруженную функцию-операцию, и объясним, как перегруженная функция-операция работает. Перегруженная функция-операция приведения может быть определена для преобразования объектов определенных пользователем типов в объекты встроенных типов или в объекты других определенных пользователем типов. Прототипы А::operator int{) const; A::operator otherClassO const; объявляют перегруженные функции-операции приведения для преобразования объекта определенного пользователем типа А в целое и для преобразования объекта определенного пользователем типа А в объект другого определенного пользователем типа otherClass. Одной из приятных особенностей операций приведения и конструкторов преобразований является то, что при необходимости компилятор может вызывать эти функции автоматически для создания временных объектов. Например, если в программе в том месте, где нормально ожидается char*, появился объект S определенного пользователем типа String, например, в операторе cout << s; то в этом случае компилятор вызывает перегруженную функцию-операцию приведения operator char* для преобразования объекта в char* и использует в выражении результирующий char*. Эта операция приведения для нашего класса String позволяет не перегружать операцию поместить в поток, предназначенную для вывода String с использованием cout.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |