20 января 2010 в 19:41
Перегрузка операций (operator overload) в C++
Сегодня мы познакомимся с замечательной возможностью нашего любомого языка C++ - перегрузкой операций. Но сначала разберёмся, для чего это нужно.
С базовыми типами вы можете использовать любые операции: +, -, *, ++, = и многие другие. Например:
int a=2,b=3,c;
c = a + b;
Здесь над переменными типа int сначала выполняется операция +, а затем результат присваивается переменной c с помощью операции =. Над классами такое проделать не получится. Создадим простой класс:
class Counter { public: int counter; Counter() : c(0) {} }; Counter a,b,c; a.counter = 2; b.counter = 3; c = a + b;
Здесь компилятор выдаст ошибку на последней строке: он не знает как именно нужно действовать при использовании операций = и + над объектами класса Counter. Можно решить данную проблему вот так:
class Counter { public: int counter; Counter() : count(0) {} void AddCounters (Counter& a, Counter& b) { counter = a.counter + b.counter; } }; Counter a,b,c; a.counter = 2; b.counter = 3; c.AddCounters(a,b);
Согласитесь, использование операции + и = в данном случае сделало бы программу более понятной. Так вот, чтобы использовать стандартные операции C++ с классами, эти операции нужно перегрузить (overload).
Перегрузка унарных операций
Начнём с простых операций - унарных. Прежде всего нас интересует инкремент. При использовании данной операции над базовыми типами, к переменной можно прибавить или отнять единицу:
int a=1; ++a; // a = 2; --a; // a = 1;
Теперь научим класс Counter использовать преинкремент (предекремент):
class Counter { private: counter; public: Counter() : counter(0) {} void operator++ () { counter += 1; // Можно также counter++ или ++counter - // это не имеет значения в данном случае. } }; Counter a; ++a; ++a; ++a;
Этот код работает. При использовании операции ++ (важно чтобы этот знак находился до идентификатора!) над объектом класса Counter, происходит увеличение переменной counter объекта a.
В данном примере мы перегрузили операцию ++. Делается это созданием метода внутри класса. Единственной важной особенностью данного метода - имя идентификатора. Имя идентификатора для перегруженных операций состоит из ключевого слова operator и названия операции. Во всём остальном этот метод определяется как и любые другие.
Использовать перегруженные операции с пользовательскими типами очень просто - так же как и с обычными типами данных.
Перегрузка постфиксных операций
Примеры постфиксной операции:
int a = 3;
a++;
a--;
То есть, здесь знак операции ставится после имени идентификатора. Для использования постфиксных операций с пользовательскими типами данных нужно совсем немного:
public: void operator++ () { counter += 1; } void operator++ (int) { counter += 1; }
Единственным отличием префиксной операции от постфиксной - ключевое слово int в списке аргументов. Но int - это не аргумент! Это слово говорит, что перегружается постфиксная операция. Теперь операцию ++ можно использовать как перед идентификатором объекта, так и после:
Counter a;
++a;
++a;
a++;
a++;
Перегрузка бинарных операций
Перегрузка операций с двумя аргументами очень похожа на перегрузку бинарных операций:
Counter operator+ (Counter t) { Counter summ; summ.counter = counter + t.counter; return summ; } Counter c1,c2,c3; c1.counter = 3; c2.counter = 2; c3 = c1 + c2;
Какая переменная вызовет функцию operator+? В перегруженных бинарных операциях всегда вызывается метод левого операнда. В данном случае метод operator+ вызывает объект c1.
В метод мы передаём аргумент. Аргументом всегда является правый операнд.
Кроме того, в данном случае операция + должна вернуть какой-то результат, чтобы присвоить его объекту c3. Мы возвращаем объект Counter. Возвращаемое значение присваивается переменной c3.
Заметьте, мы перегрузили операцию +, но не перегружали операцию =! Конечно же нужно добавить этот метод к классу Counter:
Counter operator= (Counter t) { Counter assign; counter = t.counter; assign.counter = t.counter; return assign; }
Внутри метода мы создали дополнительную переменную assign. Данная переменная используется, чтобы можно было работать вот с таким кодом:
Counter c1(5),c2,c3;
c3 = c2 = c1;
Хотя, для возвращаемого значения можно воспользоваться и более элегантными способами, с которыми мы вскоре познакомимся.
комментарии отсутствуют
авторизуйтесь