суббота, 5 декабря 2009 г.

6.15. Тонкий момент: возвращение ссылки на закрытые данные-элементы

Ссылка на объект сама по себе является псевдонимом объекта и, следо­вательно, может быть использована с левой стороны оператора присваивания. Таким образом, ссылка является вполне допустимой L-величиной, которая может получать значение. Единственный (к сожалению!) способ использовать эту возможность — иметь открытую функцию-элемент класса, возвращаю­щую неконстантную ссылку на закрытый элемент данных этого класса.
Рисунок 6.11 использует упрощенную версию класса Time для демон­страции возвращения ссылки на закрытый элемент данных. Такое возвра­щение в действительности осуществляется вызовом псевдонима функции bad- SetHour для закрытого элемента данных hour. Этот вызов функции можно использовать во всех отношениях так же, как закрытый элемент данных, включая его как L-величину в оператор присваивания!
Никогда не возвращайте из открытой функции-элемента неконстантную ссылку (или
указатель) на закрытый элемент данных. Возвращение такой ссылки нарушает ин­капсуляцию класса.
Программа начинается объявлением объекта t класса Time и ссылкой hour- Ref, которой присвоено значение, возвращенное вызовом t.badSetHour(20). Про­грамма отображает на экране значение псевдонима hourRef. Далее этот псев­доним используется для установки значения hour равным 30 (неправильное значение) и это значение снова отображается на экране. В конце как L-величина используется вызов самой функции, ему присваивается значение 74 (другое не­правильное значение), которое тоже отображается на экране.

// TIME4.H
// Объявление класса Time.
// Функции-элементы, определены в TIME4.CPP
// Предотвращение многократного включения заголовочного файла lifndef Т1МЕ4_Н #define Т1МЕ4_Н
class Time { public:
Time (int = 0, int = 0,int = 0); void setTime(int, int, int); int getHour ();
int SbadSetHour(int);        // ОПАСНОЕ возвращение ссылки
private:
int hour; int minute; int second;
} ;
lendif
Рис. 6.11. Возвращение ссылки на закрытый элементу данных (часть 1 из 3) // TIME4.CPP
// Определения функций-элементов класса Time. # include "t ime 4.h" #include
// Функция конструктор для задания начальных значений // закрытым данным вызывает функцию-элемент setTime, чтобы // установить значения переменных по умолчанию равными нулю // (смотри определение класса).
Time::Time(int hr, int min, int sec) { setTime(hr, min, sec); }
// Установка значений часов, минут, секунд.
void Time::setTime(int h, int m, int s) {
hour = (h >= 0 && h < 24) ? h : 0; minute = (m >= 0 && m < 60) ? m : 0; second = (s >= 0 && s < 60) ?s : 0;
}
// Установка значения часа
int Time::getHour() { return hour; )
II ПЛОХАЯ ПРАКТИКА ПРОГРАММИРОВАНИЯ: // Возвращение ссылки на закрытый элемент данных.
int STime : -.badSetHour (int hh) {
return hour;
// ОПАСНОЕ возвращение ссылки

Рис. 6.11. Возвращение ссылки на закрытый элементу данных (часть 2 из 3)

hour = (hh >= 0 && hh < 24) ? hh : 0;

// FIG6_11.CPP
// Демонстрация открытой функции-элемента, которая

// возвращает ссылку на закрытый элемент данных.
// Класс Time для этого примера укорочен.

iinclude iinclude "time4.h"
НИИ
^ main()
Time t;
.      int shourRef = t.badSetHour(20);
Щ
cout << "Часы перед изменением: " << hourRef « endl; с     hourRef = 30; // неправильное изменен­
ное значение
cout << "Часы после изменения: " << t.getHour() << endl;
// ОПАСНОСТЬ: вызов функции, которая возвращает ссылку, // может быть использован как L-величина. t.badSetHour(12) = 74;
cout << endl << "***********************************" << endl « "ПЛОХАЯ ПРАКТИКА ПРОГРАММИРОВАНИЯ!!!" « endl << "badSetHour как L-величина, часы: " « t.getHour()
<< endl << "***********************************" << endl*
return 0; -a }
чи^, Часы перед изменением: 20
V Часы после изменения: 30
***********************************
' ПЛОХАЯ ПРАКТИКА ПРОГРАММИРОВАНИЯ!!! ^^^ badSetHour как L-величина, часы: 74
нн ***********************************
Рис. 6.11. Возвращение ссылки на закрытый элементу данных (часть 3 из 3)

Комментариев нет:

Отправить комментарий