Программирование >>  Инициализация объектов класса, структура 

1 ... 234 235 236 [ 237 ] 238 239 240 ... 395


bool operator==( const String s, const String s );

видимости пространства имен:

bool operator==( const String s, const char * );

Обратите внимание, что эти глобальные перегруженные операторы имеют на один параметр больше, чем операторы-члены. Если оператор является членом класса, то первым параметром неявно передается указатель this. То есть для операторов-членов выражение

flower == lily

переписывается компилятором в виде:

flower.operator==( lily )

на левый операнд flower в определении перегруженного оператора-члена можно сослаться с помощью this. (Указатель this введен в разделе 13.4.) В случае глобального перегруженного оператора параметр, представляющий левый операнд, должен быть задан явно.

Тогда выражение

flower == lily вызывает оператор

bool operator==( const String s, const char * );

Непонятно, какой оператор вызывается для второго случая использования оператора равенства:

if ( Text( tulip ) == flower ) вызывается Text::operator==()

Следовательно, чтобы найти подходящий для сравнения оператор равенства, компилятору придется просмотреть все определения классов в поисках конструктора, способного привести левый операнд к некоторому типу класса. Затем для каждого из таких типов нужно проверить все ассоциированные с ним перегруженные операторы равенства, чтобы понять, может ли хоть один из них выполнить сравнение. А после этого компилятор должен решить, какая из найденных комбинаций конструктора и оператора равенства (если таковые нашлись) лучше всего соответствует операнду в правой части! Если потребовать от компилятора выполнения всех этих действий, то время трансляции программ С++ резко возрастет. Вместо этого компилятор просматривает только перегруженные операторы, определенные как члены класса левого операнда (и его базовых классов, как мы покажем в главе 19).

Разрешается, однако, определять перегруженные операторы, не являющиеся членами класса. При анализе строки в miain(), вызвавшей ошибку компиляции, подобные операторы принимались во внимание. Таким образом, сравнение, в котором С-строка стоит в левой части, можно сделать корректным, если заменить операторы равенства, являющиеся членами класса String, на операторы равенства, объявленные в области



bool operator==( const char *, const String s );

Предоставлять ли только этот оператор или еще два:

bool operator==( const String s, const char * );

зависит от того, насколько велики затрата: на преобразование из С-строки в String во время выполнения, то есть от стоимости дополнительных вызовов конструктора в программах, пользующихся нашим классом String. Если оператор равенства будет часто использоваться для сравнения С-строк и объектов , то лучше предоставить все три варианта. (Мы вернемся к вопросу эффективности в разделе, посвященном друзьям.

Подробнее о приведении к типу класса с помощью конструкторов мы расскажем в разделе 15.9; в разделе 15.10 речь пойдет о разрешении перегрузки функций с помощью описанных преобразований, а в разделе 15.12 - о разрешении перегрузки операторов.)

Итак, на основе чего принимается решение, делать ли оператор членом класса или членом пространства имен? В некоторых случаях у программиста просто нет выбора:

если перегруженный оператор является членом класса, то он вызывается лишь при условии, что левым операндом служит член этого класса. Если же левый операнд имеет другой тин, оператор обязан быть членом пространства имен;

язык требует, чтобы операторы присваивания ( = ), взятия индекса ( [] ), вызова ( () ) и доступа к членам но стрелке ( -> ) были определены как члены класса. В противном случае выдается сообщение об ошибке компиляции:

tulip == flower

М1 ведь не определили такой перегруженный оператор:

bool operator==( const char *, const String s );

Но это необязательно. Когда перегруженный оператор является функцией в пространстве имен, то как для первого, так и для второго его параметра (для левого и правого операндов) рассматриваются возможные преобразования, т.е. компилятор интерпретирует второе использование оператора равенства как

operator==( String( tulip ), flower ); и вызывает для выполнения сравнения следующий перегруженный оператор:

bool operator==( const String s, const String s );

Но тогда зачем мы предоставили второй перегруженный оператор:

bool operator==( const String s, const char * );

Преобразование тина из С-строки в класс String может быть применено и к правому операнду. Функция miain() будет компилироваться без ошибок, если просто определить в пространстве имен перегруженный оператор, принимающий два операнда String:

bool operator==( const String s, const String s );



ошибка: должен быть членом класса chars operator[]( String s, int ix );

(Подробнее оператор присваивания рассматривается в разделе 15.3, взятия индекса - в разделе 15.4, вызова - в разделе 15.5, а оператор доступа к члену по стрелке - в разделе

15.6.)

В остальных случаях решение принимает проектировщик класса. Симметричные операторы, например оператор равенства, лучше определять в пространстве имен, если членом класса может быть любой операнд (как в 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 ;

inline bool operator==( const String sstr, const char *s ) {

return strcmp( str.c str(), s ) ? false : true ;

String в пространстве имен:

15.1.2. Имена перегруженных операторов

Перегружать можно только предопределенные операторы языка С++ (см. табл. 15.1).

Таблица 15.1. Перегружаемые операторы

&

<

>

<-

>-

<<

>>

&&

&=

<<-

>>-

->

->*

new[]

delete

delete[]

Проектировщик класса не вправе объявить перегруженным оператор с другим именем.

Так, при попытке объявить оператор ** для возведения сообщение об ошибке.

в степень компилятор выдаст

неперегружаемые операторы

Следующие четыре оператора языка С++ не могут быть перегружены:



1 ... 234 235 236 [ 237 ] 238 239 240 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика