русс | укр

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

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

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

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


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

Использование ссылок для перегрузки унарных операторов


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


Независимые ссылки

Возврат ссылок

Функция может возвращать ссылку. В результате такая функция может использоваться в левой части оператора присваивания! В качестве примера рассмотрим следующую простую программу:

#include <iostream.h>



char& replace(int i, char *s) // возврат ссылки

{

return s[i];

}

char s[80] = "Hello There";

int main ()

{

replace(5) = 'X'; // присвоение Х пробелу после Hello

cout << s;

return 0;

}

Эта программа заменяет пробел между словами “Hello” и “There” символом ‘Х’. В результате программа выводит на экран «HelloXThere».

Функция replace() в соответствии со своим объявлением возвращает ссылку на символ. В соответствии со своей реализацией функция replace() возвращает ссылку на элемент масси­ва s, определяющийся индексом i. Далее возвращаемая функцией replace() ссылка используется функцией main() для присвоения элементу буквы «X».

Хотя в первую очередь ссылки включены в C++ для поддержки передачи параметров по ссылке и возвращения результата функции по ссылке, можно объявлять переменные ссылочного типа и как самостоятельные переменные. В таком случае они называются независимыми ссылками (independent references). Однако в таком случае их возможности серьезно ограничиваются.

Переменные ссылочного типа всегда должны указывать на какой-либо объект, поэтому они должны быть инициализированы при своем объявлении. В общем слу­чае это означает присвоение им адреса уже объявленного объекта. После этого переменная ссылоч­ного типа может использоваться всюду, где используется переменная, на которую она ссылается. Фактически между обеими переменными нет разницы. В качестве примера рассмотрим программу:

#include <iostream.h>



int main()

{

int j, k;

int &i = j; // независимая ссылка на j

j = 10;

cout << j << " " << i; // выводит 10 10

k = 121;

i = k; // копирование значения, а не адреса к в j

cout << "\n" << j; // выводит 121

return 0;

}

Программа выдаст следующие данные:

10 10

Адрес, на который указывает ссылочная переменная i, фиксирован и не может меняться. Так при выполнении присвоения i = k величина к копируется в j.

Вот другой пример. Инструкция i++ не вызывает изменения адреса. Вместо этого значение переменной k увеличивается на 1. (Надо помнить, что ссылки не являются указателями.)

Ссылочные переменные могут указывать на константы:

const int &i = 100;

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

point point::operator++()

{

х++; У++; z++;

return *this;

}

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

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

class point

{

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

public:

friend point operator+(point p1, point p2);

point operator=(point p2); // p1 подразумевается

friend point operator++(point &p1);

void show();

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

};

point operator++(point &p1)

{

p1.x++; p1.y++; p1.z++;

return p1;

}

ПАМЯТКА: Для перегрузки операторов следует пользоваться функциями-члена­ми. Функции-друзья предназначаются в C++ большей частью для специальных си­туаций.

4.10 Перегрузка оператора []

Кроме нескольких вышеперечисленных операторов, можно перегрузить и многие другие операторы C++. Большей частью требуется перегружать стандартные операторы, такие как арифметические, логические или операторы отношения. Тем не менее, имеется один достаточно экзотичный опера­тор, который бывает полезно перегружать: []. В C++ оператор [] при перегрузке рассматривается как бинарный оператор. Его следует перегружать с помощью функции-члена. Нельзя использовать дружественную функцию. Общая форма функции-оператора operator[]() имеет следующий вид:

тип имя_класса::operator[](int i)

Параметр не обязан иметь тип int, но поскольку функция operator[]() обычно используется для индексации массива, то в таком качестве обычно используется целое значение. Для заданного объекта A выражение

A[3]

преобразуется в вызов функции operator[]():

operator[](3)

В таком случае значение индекса передается функции operator[]() в качестве явного параметра. Указатель this указывает на объект A, тот самый, который вызывает функцию.

В следующей программе класс array содержит массив из трех переменных целого типа. Конст­руктор инициализирует каждый элемент массива заданным значением. Перегруженная функция-оператор operator[]() возвращает величину элемента массива, определяемого индексом, передава­емым в качестве параметра.

#include <iostream.h>



class array

{

int a[3];

public:

array(int i, int j, int k) { a[0] = i; a[1] = j; a[2] = k; }

int operator[](int i) { return a[i]; }

};

int main()

{

array A(1, 2, 3);

cout << A[1]; // выводит 2

return 0;

}

Можно создать функцию-оператор operator[]() таким образом, чтобы оператор [] можно было использовать как с левой, так и с правой стороны оператора присваивания. Для этого достаточно в качестве возвращаемой величины для operator[]() задать ссылку.

class array

{

int a[3];

public:

int& operator[](int i) { return a[i]; }

//…

};

Поскольку operator[]() возвращает ссылку на элемент массива, отвечающий индексу i, то он может быть использован с левой стороны операции присваивания для модификации элемента массива. Разумеется, этот оператор может быть использован и с правой стороны оператора присваивания.

Как известно, в C++ во время выполнения программы можно выйти за пределы массива, и при этом не будет выдаваться сообщение об ошибке. Одним из достоинств перегрузки оператора [] служит то, что с его помощью можно устранить такую возможность.

Если создается класс, содержащий массив, и разрешен доступ к этому массиву только через перегруженный оператор [], то можно перехватывать значение, содержащее величину индекса за пределами допустимых значений. Например, следующая программа осуществляет проверку на принадлежность значений допустимой области:

#include <iostream.h>



#include <stdlib.h>

class array

{

int a[3];

public:

array(int i, int j, int k) { a[0] = i; a[1] = j; a[2] = k; }

int& operator[](int i);

};

int& array::operator[](int i)

{

if(i<0 || i>2)

{

cout << "Boundary Error\n";

exit(1);

}

return a[i];

}

int main()

{

array A(1, 2, 3) ;

cout << A[1]; // выводит 2

A[3] = 44; // генерируется ошибка времени выполнения поскольку 3 выходит за допустимые пределы

return 0;

}

При выполнении инструкции

A[3] = 44;

оператор перехватывает ошибку выхода за границу массива.



<== предыдущая лекция | следующая лекция ==>
Передача ссылок на объекты | Наследование и спецификаторы доступа


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


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

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

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


 


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

 
 

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

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