русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Перегрузка операторов


Дата добавления: 2013-12-23; просмотров: 1598; Нарушение авторских прав


C++ поддерживает перегрузку операторов (operator overloading). За небольшими исключениями большинство операторов C++ могут быть перегружены, в результате чего они получат специаль­ное значение по отношению к определенным классам. Например, класс, определяющий связан­ный список, может использовать оператор + для того, чтобы добавлять объект к списку. Другой класс может использовать оператор + совершенно иным способом. Когда оператор перегружен, ни одно из его исходных значений не теряет смысла. Просто для определенного класса объектов определен новый оператор. Поэтому перегрузка оператора + для того, чтобы обрабатывать свя­занный список, не изменяет его действия по отношению к целым числам.

Операторные функции обычно являются либо членами, либо друзьями того класса, для которого они используются. Несмотря на большое сходство, имеется определенное различие между спосо­бами, которыми перегружаются операторные функции-члены и операторные функции-друзья.

Для того чтобы перегрузить оператор, необходимо определить, что именно означает опера­тор по отношению к тому классу, к которому он применяется. Для этого определяется функция-оператор, задающая действие оператора. Общая форма записи функции-оператора для случая, когда она является членом класса, имеет вид:

тип имя_класса::operator#(список_аргументов)

{

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

}

Здесь перегруженный оператор подставляется вместо символа #, а тип задает тип значений, возвращаемых оператором. Для того, чтобы упростить использование перегруженного оператора в сложных выражениях, в качестве возвращаемого значения часто выбирают тот же самый тип, что и класс, для которого перегружается оператор. Характер списка аргументов определяется не­сколькими факторами, как будет видно ниже.

Чтобы увидеть, как работает перегрузка операторов, начнем с простого примера. В нем созда­ется класс point, представляющий собой точку в трехмерном пространстве. Следующая про­грамма перегружает операторы + и = для класса point:



#include <iostream.h>

class point

{

double x, y, z; // трехмерные координаты

public:

point operator+(point t);

point operator=( point t);

void show();

void set(int mx, int my, int mz);

};

point point::operator+(point t)

{

point temp;

temp.x = x+t.x; temp.у = y+t.y; temp.z = z+t.z;

return temp;

}

point point::operator=(point t)

{

x = t.x; y = t.y; z = t.z;

return *this;

}

void point::show()

{

cout << x << ", " << у << ", " << z << "\n";

}

void point::set(int mx, int my, int mz)

{

x = mx; y = my; z = mz;

}

int main()

{

point a, b, c;

a.set(1, 2, 3); b.set(10, 10, 10);

а.show(); b.show();

с = a+b; // сложение а и b

с.shоw();

с = a+b+c; // сложение a, b и с

с.show();

c = b = a; // демонстрация множественного присваивания

с.show(); b.show();

return 0;

}

Эта программа выводит на экран следующие данные:

1, 2, 3

10, 10, 10

11, 12, 13

22, 24, 26

1, 2, 3

1, 2, 3

Если рассмотреть эту программу внимательно, может вызвать удивление, что обе функции-опе­ратора имеют только по одному параметру, несмотря на то, что они перегружают бинарный оператор. Это связано с тем, что при перегрузке бинарного оператора с использованием функ­ции-члена ей передается явным образом только один аргумент. Вторым аргументом служит ука­затель this, который передается ей неявно. Так, в строке

temp.х = х + t.х;

х соответствует this->x, где х ассоциировано с объектом, который вызывает функцию-оператор. Во всех случаях именно объект слева от знака операции вызывает функцию-оператор. Объект, стоящий справа от знака операции, передается функции.

При перегрузке унарной операции функция-оператор не имеет параметров, а при перегрузке бинарной операции функция-оператор имеет один параметр. (Нельзя перегрузить тернарный опе­ратор ?:.) Во всех случаях объект, активизирующий функцию-оператор, передается неявным об­разом с помощью указателя this.

Чтобы понять, как работает перегрузка операторов, тщательно проанализируем, как работа­ет предыдущая программа, начиная с перегруженного оператора +. Когда два объекта типа point подвергаются воздействию оператора +, значения их соответствующих координат скла­дываются, как это показано в функции operator+(), ассоциированной с данным классом. Обра­тим, однако, внимание, что функция не модифицирует значений операндов. Вместо этого она возвращает объект типа point, содержащий результат выполнения операции. Чтобы понять, почему оператор + не изменяет содержимого объектов, можно представить себе стандартный арифметический оператор +, примененный следующим образом: 10 + 12. Результатом этой опе­рации является 22, однако ни 10 ни 12 от этого не изменились. Хотя не существует правила о том, что перегруженный оператор не может изменять значений своих операндов, обычно име­ет смысл следовать ему. Если вернуться к данному примеру, то нежелательно, чтобы оператор + изменял содержание операндов.

Другим ключевым моментом перегрузки оператора сложения служит то, что он возвращает объект типа point. Хотя функция может иметь в качестве значения любой допустимый тип язы­ка C++, тот факт, что она возвращает объект типа point, позволяет использовать оператор + в более сложных выражениях, таких, как а + b + с. Здесь а + b создает результат типа point. Это значение затем прибавляется к с. Если бы значением суммы а + b было значение другого типа, то мы не могли бы затем прибавить его к с.

В противоположность оператору +, оператор присваивания модифицирует свои аргументы. (В этом и заключается смысл присваивания.) Поскольку функция operator=() вызывается объектом, стоящим слева от знака равенства, то именно этот объект модифицируется при выполнении операции присваивания. Однако даже оператор присваивания обязан возвра­щать значение, поскольку как в C++, так и в С оператор присваивания порождает величину, стоящую с правой стороны равенства. Так, для того, чтобы выражение следующего вида

а = b = с = d;

было допустимым, необходимо, чтобы оператор operator=() возвращал объект, на который ука­зывает указатель this и который будет объектом, стоящим с левой стороны оператора присваива­ния. Если следовать этому правилу, то можно выполнять множественное присваивание.

Можно перегрузить унарные операторы, такие как ++ или --. Как уже говорилось ранее, при перегрузке унарного оператора с использованием функции-члена, эта функция-член не имеет аргументов. Вместо этого операция выполняется над объектом, осуществляющим вызов функции-оператора путем неявной передачи указателя this. В качестве примера ниже рассмотрена модификация предыдущей программы, в которой определяется оператор-инкремент для объекта типа point:

#include <iostream.h>

class point

{

double x, y, z; // трехмерные координаты

public:

point operator+(point t);

point operator=( point t);

point operator++(); //оператор инкремент

void show();

void set(int mx, int my, int mz);

};

point point::operator++()

{

x++; у++; z++;

return *this;

}

//остальные функции остались прежними

int main()

{

point a;

a.set(1, 2, 3);

a.show();

++a; // увеличение a

a.show();

return 0;

}

В ранних версиях C++ было невозможно определить, предшествует или следует за операндом перегруженный оператор ++ или --. Например, для объекта a следующие две инструкции были идентичными:

a++; ++a;

Однако более поздние версии C++ позволяют различать префиксную и постфиксную форму опе­раторов инкремента и декремента. Для этого программа должна определить две версии функции operator++(). Одна их них должна быть такой же, как показано в предыдущей программе. Дру­гая объявляется следующим образом:

point operator++(int x);

Если ++ предшествует операнду, то вызывается функция operator++(). Если же ++ следует за операндом, то тогда вызывается функция operator++(int x), где х принимает значение 0.

Действие перегруженного оператора по отношению к тому классу, для которого он опреде­лен, не обязательно должно соответствовать каким-либо образом действию этого оператора для встроенных типов C++. Например, операторы << и >> применительно к cout и cin имеют мало общего с их действием на переменные целого типа. Однако, исходя из стремления сделать код более легко читаемым и хорошо структурированным, желательно, чтобы перегруженные опера­торы соответствовали, там, где это возможно, смыслу исходных операторов. Например, оператор + по отношению к классу point концептуально сходен с оператором + для переменных целого типа. Мало пользы, например, можно ожидать от такого оператора +, действие которого на соответствующий класс будет напоминать действие оператора ||. Хотя можно придать перегру­женному оператору любой смысл по своему выбору, но для ясности его применения желательно, чтобы его новое значение соотносилось с исходным значением.

Имеются некоторые ограничения на перегрузку операторов. Во-первых, нельзя изменить при­оритет оператора. Во-вторых, нельзя изменить число операндов оператора. Наконец, за исклю­чением оператора присваивания, перегруженные операторы наследуются любым производным классом. Каждый класс обязан определить явным образом свой собственный перегруженный опе­ратор =, если он требуется для каких-либо целей. Разумеется, производные классы могут пере­грузить любой оператор, включая и тот, который был перегружен базовым классом. Следующие операторы не могут быть перегружены: . :: ? .* # ##



<== предыдущая лекция | следующая лекция ==>
Указатель this | Дружественная функция-оператор


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.005 сек.