|
Программирование >> Инициализация объектов класса, структура
ошибка: нельзя переопредеть встроенн оператор сложения int так, чтобы он проверял результат на переполнение. int operator+( int, int ); Нельзя также определять дополнительные операторы для встроенных типов данных, например добавить к множеству встроенных операций operator+ для сложения двух массивов. Перегруженный оператор определяется исключительно для операндов типа класса или перечисления и может быть объявлен только как член класса или пространства имен, принимая хотя бы один параметр типа класса или перечисления (переданный по значению или по ссылке). Предопределенные приоритета: операторов (см. раздел 4.13) изменить нельзя. Независимо от типа класса и реализации оператора в инструкции x == y + z; всегда сначала выполняется operator+, а затем operator==; однако помощью скобок порядок можно изменить. Предопределенная арность операторов также должна быть сохранена. К примеру, унарный логический оператор НЕ нельзя определить как бинарный оператор для двух объектов класса String. Следующая реализация некорректна и приведет к ошибке некорректно: ! - это унарн оператор bool operator!( const String ss1, const String ss2 ) { return ( strcmp( s1.c str(), s2.c str() ) != 0 ); компиляции: Для встроенных типов четыре предопределенных оператора ( + , - , * и s ) используются либо как унарные, либо как бинарные. В любом из этих качеств они могут быть перегружены. Для всех перегруженных операторов, за исключением operator() , недопустимы аргументы по умолчанию. 15.1.3. Разработка перегруженных операторов Операторы присваивания, взятия адреса и оператор занятая имеют предопределенный смысл, если операндами являются объекты типа класса. Но их можно и перегружать. Семантика всех остальных операторов, когда они применяются к таким операндам, должна быть явно задана разработчиком. Выбор предоставляемых операторов зависит от ожидаемого использования класса. Предопределенное назначение оператора нельзя изменить для встроенных типов. Например, не разрешается переопределить встроенный оператор сложения целых чисел String s1( C ); String s2( ++ ); копирования: s1 = s1 + s2; s1 == C++ Но этого недостаточно для поддержки составного оператора присваивания s1 += s2; Его следует определить явно, так, чтобы он поддерживал ожидаемую семантику. Упражнение 15.1 Почему при выполнении следующего сравнения не вызывается перегруженный оператор operator==(const Strings, const Strings) : cobble == stone Упражнение 15.2 Начинать следует с определения его открытого интерфейса. Набор открытых функций-членов формируется с учетом операций, которые класс должен предоставлять пользователям. Затем принимается решение, какие функции стоит реализовать в виде перегруженных операторов. После определения открытого интерфейса класса проверьте, есть ли логическое соответствие между операциями и операторами: isEmiptyO становится оператором ЛОГИЧЕСКОЕ НЕ , operator!(). isEqual() становится оператором равенства, operator==(). copy() становится оператором присваивания, operator=() . У каждого оператора есть некоторая естественная семантика. Так, бинарный + всегда ассоциируется со сложением, а его отображение на аналогичную операцию с классом может оказаться удобной и краткой нотацией. Например, для матричного типа сложение двух матриц является вполне подходящим расширением бинарного плюса. Примером неправильного использования перегрузки операторов является определение operator+() как операции вычитания, что бессмысленно: не согласующаяся с интуицией семантика опасна. Такой оператор одинаково хорошо поддерживает несколько различных интерпретаций. Безупречно четкое и обоснованное объяснение того, что делает operator+(), вряд ли устроит пользователей класса String, полагающих, что он служит для конкатенации строк. Если семантика перегруженного оператора неочевидна, то лучше его не предоставлять. Эквивалентность семантики составного оператора и соответствующей последовательности простых операторов для встроенных типов (например, эквивалентность оператора +, за которым следует =, и составного оператора +=) должна быть явно поддержана и для класса. Предположим, для String определены как operator+() , так и operator=() для поддержки операций конкатенации и почленного String != String String != С-стро: С-строка таких сравнениях: С-строка != String Объясните, почему вы решили реализовать один или несколько операторов. Упражнение 15.3 Выявите те функции-члены класса Screen, реализованного в главе 13 (разделы 13.3, 13.4 и 13.6), которые можно перегружать. Упражнение 15.4 Объясните, почему перегруженные операторы ввода и вывода, определенные для класса String из раздела 3.15, объявлены как глобальные функции, а не функции-члены. Упражнение 15.5 Реализуйте перегруженные операторы ввода и вывода для класса Screen из главы 13. 15.2. Друзья Рассмотрим еще раз перегруженные операторы равенства для класса String, определенные в области видимости пространства имен. Оператор равенства для двух bool operator==( const String sstr1, const String sstr2 ) { if ( str1.size() != str2.size() ) return false; return strcmp( str1.c str(), str2.c str() ) ? false : true; объектов String выглядит следующим образом: bool String::operator==( const String srhs ) const { if ( size != rhs. size ) return false; return strcmp( string, rhs. string ) ? false : true; Сравните это определение с определением того же оператора как функции-члена: Нам пришлось модифицировать способ обращения к закрытым членам класса String. Поскольку новый оператор равенства - это глобальная функция, а не функция-член, у него нет доступа к закрытым членам класса String. Для получения размера объекта String и лежащей в его основе С-строки символов используются функции-члены size() и c str() . Напишите перегруженные операторы неравенства, которые могут быть использованы в
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |