Язык программирования C++. Вводный курс

Разрешение перегрузки и операторы A


В классах могут быть объявлены перегруженные операторы и конвертеры. Предположим, при инициализации встретился оператор сложения:

SomeClass sc;

int iobj = sc + 3;

Как компилятор решает, что следует сделать: вызвать перегруженный оператор для класса SomeClass или конвертировать операнд sc во встроенный тип, а затем уже воспользоваться встроенным оператором?

Ответ зависит от множества перегруженных операторов и конвертеров, определенных в SomeClass. При выборе оператора для выполнения сложения применяется процесс разрешения перегрузки функции. В данном разделе мы расскажем, как этот процесс позволяет выбрать нужный оператор, когда операндами являются объекты типа класса.

При разрешении перегрузки используется все та же процедура из трех шагов, представленная в разделе 9.2:

1.      Отбор функций-кандидатов.

2.      Отбор устоявших функций.



3.      Выбор наилучшей из устоявших функции.

Рассмотрим эти шаги более детально.

Разрешение перегрузки функции не применяется, если все операнды имеют встроенные типы. В таком случае гарантированно употребляется встроенный оператор. (Использование операторов с операндами встроенных типов описано в главе 4.) Например:

class SmallInt {

public:

   SmallInt( int );

};

SmallInt operator+ ( const SmallInt &, const SmallInt & );

void func() {

   int i1, i2;

   int i3 = i1 + i2;

}

Поскольку операнды i1 и i2

имеют тип int, а не тип класса, то при сложении используется встроенный оператор +. Перегруженный operator+(const SmallInt

&, const SmallInt &)

игнорируется, хотя операнды можно привести к типу SmallInt с помощью определенного пользователем преобразования в виде конструктора SmallInt(int). Описанный ниже процесс разрешения перегрузки в таких ситуациях не применяется.

Кроме того, разрешение перегрузки для операторов употребляется только в случае использования операторного синтаксиса:

void func() {

   SmallInt si(98);

   int iobj = 65;

   int res = si + iobj;  // использован операторный синтаксис

}

Если вместо этого использовать синтаксис вызова функции:

int res = operator+( si, iobj );  // синтаксис вызова функции

то применяется процедура разрешения перегрузки для функций в пространстве имен (см. раздел 15.10). Если же использован синтаксис вызова функции-члена:

// синтаксис вызова функции-члена

int res = si.operator+( iobj );

то работает соответствующая процедура для функций-членов (см. раздел 15.11).



Содержание раздела