Студопедия — Глобальная перегрузка.
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Глобальная перегрузка.






В C++ кроме двух известных вам разновидностей перегрузки (перегрузка в классе и дружественная перегрузка), существует еще одно понятие - глобальная перегрузка, осуществляемая во внешней области видимости.

Допустим, переменные a и b объявлены как объекты класса C. В классе C определен оператор C::operator+(C), поэтому

  a+b означает a.operator+(b)

Однако, также возможна глобальная перегрузка оператора +:

  C operator+(C,C) {....}

Такой вариант перегрузки тоже применим к выражению a+b, где a и b передаются соответственно в первом и втором параметрах функции. Из этих двух форм предпочтительной считается перегрузка в классе. Т. к. вторая форма требует открытого обращения к членам класса, а это отрицательно отражается на строгой эстетике инкапсуляции. Вторая форма может быть более удобной для адаптации классов, которые находятся в библиотеках, где исходный текст невозможно изменить и перекомпилировать.То есть добавить в класс перегрузку в качестве метода класса нереально.

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

Тем не менее, глобальная перегрузка операторов обеспечивает симметрию, которая также обладает эстетической ценностью. Рассмотрим пример:

#include <iostream> using namespace std;   // класс "точка" class Point { // координаты точки int X; int Y; public:   // конструктор Point(int iX,int iY){ X=iX; Y=iY; }   //показ на экран void Show(){ cout<<"\n+++++++++++++++++++++\n"; cout<<"X = "<<X<<"\tY = "<<Y; cout<<"\n+++++++++++++++++++++\n"; }   // перегруженный оператор + // метод класса для ситуации Point+int Point&operator+(int d){ Point P(0,0); P.X=X+d; P.Y=Y+d; return P; } // функции доступа к // privat-членам без них // глобальная перегрузка невозможна int GetX() const{ return X; } int GetY() const{ return Y; } void SetX(int iX){ X=iX; } void SetY(int iY){ Y=iY; } };   // глобальная перегрузка // для ситуации int + Point // доступ к private-членам // через специальные функции Point&operator+(int d,Point&Z){ Point P(0,0); P.SetX(d+Z.GetX()); P.SetY(d+Z.GetY()); return P; }   void main() { // создание объекта Point A(3,2); A.Show();   //оператор-метод + Point B=A+5; B.Show();   //глобальный оператор Point C=2+A; C.Show(); }

Без глобальной перегрузки задача int + Point не решается. Поскольку мы не можем получить доступ к "родному” целому типу (то есть к типу int) и переопределить его операции, обеспечить симметрию простым определением операторов класса не удастся. Потребуется решение с глобальными функциями.

Примечание:Здесь мы могли бы применить дружественную перегрузку, и таким образом избавиться от "функций доступа к private-членам". Однако, если бы тело класса Point было бы для нас закрыто, то вписать в него функцию-друга было бы нереально.

Перегрузка ввода/вывода данных.

Для того, что бы закрепить новую полученную информацию о перегрузке рассмотрим возможность перегрузить операторы << и >>. Для начала немного информации -

Выполнение любой программы С++ начинаются с набором предопределенных открытых потоков, объявленных как объекты классов в файле-библиотеке iostream. Среди них есть два часто используемых нами объекта - это cin и cout.

cin - объект класса istream (Потоковый класс общего назначения для ввода, являющийся базовым классом для других потоков ввода)

cout - объект класса ostream (Потоковый класс общего назначения для вывода, являющийся базовым классом для других потоков вывода)

Вывод в поток выполняется с помощью операции, которая является перегруженной операцией сдвига влево <<. Левым ее операндом является объект потока вывода. Правым операндом может являться любая переменная, для которой определен вывод в поток. Например, оператор cout << "Hello!\n"; приводит к выводу в предопределенный поток cout строки "Hello!".

Для ввода информации из потока используется операция извлечения, которой является перегруженная операция сдвига вправо >>. Левым операндом операции >> является объект класса istream.

Чтобы избежать неожиданностей, ввод-вывод для абстрактных типов данных должен следовать тем же соглашениям, которые используются операциями ввода и вывода для встроенных типов, а именно:

1. Возвращаемым значением для операций ввода и вывода должна являться ссылка на поток, чтобы несколько операций могли быть выполнены в одном выражении.

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

3. Чтобы разрешить доступ к закрытым данным класса, операции ввода и вывода должны быть объявлены как дружественные функции класса.

4. В операцию вывода необходимо передавать константную ссылку на объект класса, поскольку данная операция не должна модифицировать выводимые объекты.

Итак, рассмотрим пример подобной перегрузки:

  #include <iostream> using namespace std;   // класс "точка" class Point { // координаты точки int X; int Y; public:   // конструктор Point(int iX,int iY){ X=iX; Y=iY; } // дружественные функции перегрузки ввода и вывода данных friend istream& operator>>(istream& is, Point& P); friend ostream& operator<<(ostream& os, const Point& P);   }; //ввод данных через поток istream& operator>>(istream&is, Point&P){ cout<<"Set X\t"; is >> P.X; cout<<"Set Y\t"; is >> P.Y; return is; } //вывод данных через поток ostream& operator<<(ostream&os, const Point&P){ os << "X = " << P.X << '\t'; os << "Y = " << P.Y << '\n'; return os; }   void main() { // создание объекта Point A(0,0);   // одиночный ввод и вывод cin>>A; cout<<A;   // множественное выражение Point B(0,0); cin>>A>>B; cout<<A<<B; }

Примечание:Кстати!!! В одном из примеров мы использовали константный метод - метод, который не имеет право изменять поля класса. Однако, если какое-то поле объявлено со спецификатором mutable, его значение МОЖНО менять в методе типа const.







Дата добавления: 2015-10-01; просмотров: 319. Нарушение авторских прав; Мы поможем в написании вашей работы!



Картограммы и картодиаграммы Картограммы и картодиаграммы применяются для изображения географической характеристики изучаемых явлений...

Практические расчеты на срез и смятие При изучении темы обратите внимание на основные расчетные предпосылки и условности расчета...

Функция спроса населения на данный товар Функция спроса населения на данный товар: Qd=7-Р. Функция предложения: Qs= -5+2Р,где...

Аальтернативная стоимость. Кривая производственных возможностей В экономике Буридании есть 100 ед. труда с производительностью 4 м ткани или 2 кг мяса...

Классификация холодных блюд и закусок. Урок №2 Тема: Холодные блюда и закуски. Значение холодных блюд и закусок. Классификация холодных блюд и закусок. Кулинарная обработка продуктов...

ТЕРМОДИНАМИКА БИОЛОГИЧЕСКИХ СИСТЕМ. 1. Особенности термодинамического метода изучения биологических систем. Основные понятия термодинамики. Термодинамикой называется раздел физики...

Травматическая окклюзия и ее клинические признаки При пародонтите и парадонтозе резистентность тканей пародонта падает...

Реформы П.А.Столыпина Сегодня уже никто не сомневается в том, что экономическая политика П...

Виды нарушений опорно-двигательного аппарата у детей В общеупотребительном значении нарушение опорно-двигательного аппарата (ОДА) идентифицируется с нарушениями двигательных функций и определенными органическими поражениями (дефектами)...

Особенности массовой коммуникации Развитие средств связи и информации привело к возникновению явления массовой коммуникации...

Studopedia.info - Студопедия - 2014-2024 год . (0.009 сек.) русская версия | украинская версия