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

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

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





В 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; просмотров: 344. Нарушение авторских прав; Мы поможем в написании вашей работы!




Расчетные и графические задания Равновесный объем - это объем, определяемый равенством спроса и предложения...


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


Обзор компонентов Multisim Компоненты – это основа любой схемы, это все элементы, из которых она состоит. Multisim оперирует с двумя категориями...


Композиция из абстрактных геометрических фигур Данная композиция состоит из линий, штриховки, абстрактных геометрических форм...

ЛЕЧЕБНО-ПРОФИЛАКТИЧЕСКОЙ ПОМОЩИ НАСЕЛЕНИЮ В УСЛОВИЯХ ОМС 001. Основными путями развития поликлинической помощи взрослому населению в новых экономических условиях являются все...

МЕТОДИКА ИЗУЧЕНИЯ МОРФЕМНОГО СОСТАВА СЛОВА В НАЧАЛЬНЫХ КЛАССАХ В практике речевого общения широко известен следующий факт: как взрослые...

СИНТАКСИЧЕСКАЯ РАБОТА В СИСТЕМЕ РАЗВИТИЯ РЕЧИ УЧАЩИХСЯ В языке различаются уровни — уровень слова (лексический), уровень словосочетания и предложения (синтаксический) и уровень Словосочетание в этом смысле может рассматриваться как переходное звено от лексического уровня к синтаксическому...

Прием и регистрация больных Пути госпитализации больных в стационар могут быть различны. В цен­тральное приемное отделение больные могут быть доставлены: 1) машиной скорой медицинской помощи в случае возникновения остро­го или обострения хронического заболевания...

ПУНКЦИЯ И КАТЕТЕРИЗАЦИЯ ПОДКЛЮЧИЧНОЙ ВЕНЫ   Пункцию и катетеризацию подключичной вены обычно производит хирург или анестезиолог, иногда — специально обученный терапевт...

Ситуация 26. ПРОВЕРЕНО МИНЗДРАВОМ   Станислав Свердлов закончил российско-американский факультет менеджмента Томского государственного университета...

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