Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Мизрохи С.В. -> "Turbo Pascal и объектно-ориентированное программирование" -> 41

Turbo Pascal и объектно-ориентированное программирование - Мизрохи С.В.

Мизрохи С.В. Turbo Pascal и объектно-ориентированное программирование — М.: Финансы и статистика , 1992. — 192 c.
ISBN 5-279-00903-2
Скачать (прямая ссылка): efektispolzc2000.djvu
Предыдущая << 1 .. 35 36 37 38 39 40 < 41 > 42 43 44 45 46 47 .. 105 >> Следующая

Поскольку в реальном коде встречаются обе формы, следует привыкать к ним обеим.
Некоторые из наиболее важных применений const связаны с их использованием в объявлениях функций. Внутри объявления функции const может относиться к типу, возвращаемому функцией, к индивидуальным аріументам и (для Функций-членов) к функциям в целом.
Делая значение, возвращаемое функцией, константным, можно, не поступаясь безопасностью или эффективностью, уменьшить вероятность ошибки пользователя. В действительности, как показано в правиле 29, использование const в качестве возвращаемой величины увеличивает безопасность и эффективность Функций в тех случаях, когда добиться этого другим способом невозможно.
Например, рассмотрим объявление функции operator* для рациональных Чисел, введенное в правиле 19:
const Rational operator*(const Rationalb lhs, const Rationale rhs) ;
* Согласно стандарту С++ тип "Hello" - const char [ ], который практически всегда эквивалентен const char*. Поэтому при инициализации переменных char* строками, подобными "Hello", мы Могли бы ожидать ошибки нарушения условия const. Эта практика, однако настолько распространена в С, что стандарт вводит специальное допущение для подобных инициализаций. Тем не менее вам следует их избегать, поскольку их использование не одобряется.
92
!¦¦¦III!
Классы и функции
Многие программисты удивятся, впервые увидев такое объявление. Почему результат функции operator* является объектом const? Потому, что в противном случае пользователь получил бы возможность делать вещи, которые иначе как надругательством над здравым смыслом не назовешь:
Rational а, Ь, с;
(а * b) = с; // Присваивание произведению а*Ы
Я не знаю, с какой стати программисту пришло бы в голову присваивать зна-1 ченне произведению двух чисел, но могу сказать точно, что для a, b и с встроенных типов это было бы однозначно некорректной операцией. Один из критериев хорошо определенного пользовательского типа - отсутствие необоснованной несовмес-1 тимости с поведением встроенных типов, а возможность присваивания значения произведению двух чисел мне кажется совершенно необоснованной. Объявление возвращаемого типа функции operator* как const препятствует этому, поэтому оно вполне целесообразно.
В отношении аргументов с модификатором const невозможно прибавить ничего нового; они просто аналогичны локальным объектам с const. Функции-{ члены с const - совсем другое дело.
Цель функций-членов с const безусловно состоит в том, чтобы определить, какие функции-члены могжно вызвать для константных объектов const. Многие упускают из виду, что функции, отличающиеся только объявлением const, могут быть перегружены. Это, однако, очень важное свойство С++. Давайте еще раз рассмотрим класс String:
class String { public:
Il operator И для неконстантных объектов. char& operator[](int position) { return data [position]; } Il operator!] для константных объектов, const char& operator!] (int position) const { return data[position]; } private:
char *data;
>;
String si = "Hello";
cout « sl[0]; Il Вызывает неконстантный String: :operator[] .
const String s2 = "World"; '
cout <x s2[0]; IS Вызывает константный String.-: operator И •
Перегружая operator [ ] и создавая различные версии с разными возвращаемыми типами, вы можете по-разному обрабатывать константные и неконстантные объекты String: /
String s = "Hello"; Il Неконстантный объект String.
cout « s[0] ; Il Правильно - считываем неконстантный объект String-
s[0] = 'х'; //Правильно - записываем неконстантный объект String-
Правило 21
.KtH
93
const String es = "World" ; // Константный объект String,
cout « cs[0] ; Il Правильно - считываем константный объект String. cs[0] = 'х'; // Ошибка! Запись в константный объект String.
Заметьте, между прочим, что ошибка здесь генерируется только значением, возвращаемым функцией operator [ ]; сами вызовы operator [ ] вполне корректны. Ошибки возникают из-за попытки присвоить значение ссылке на константный символ const char&, то есть возвращаемому типу const-версии функции operator[]const.
Обратите также внимание на то, что тип, возвращаемый operator [ ] без const, должен быть ссылкой на char - просто char не работает. Если бы operator [ ] действительно возвращал просто char, не компилировались бы предложения, подобные следующему:
S[O] = 'X';
Это объясняется тем, что возвращаемое функцией значение встроенного типа модифицировать некорректно. И даже если бы это было допустимо, тот факт, что С++ возвращает объекты по величине (см. правило 22), означал бы следующее: модифицировалась копия s. data [0 ], а не само значение s. data [0 ].
Давайте немного передохнем и пофилософствуем. Какое значение на деле имеет то, что функция-член определена с const? Существуют два широко распространенных понятия: побитовая константность и концептуальная константность.
Сторонники побитовой константности полагают, что функция-член константна, только если она не модифицирует элементы данных объекта (за исключением статических), то есть никакие биты внутри объекта. Определение побитовой константности хорошо тем, что ее нарушение легко обнаружить: компилятор просто ищет присваивания членам класса. В действительности побитовая константность -это константность, определенная в С++: функции-члены с const не могут модифицировать члены класса вызвавшего их объекта.
Предыдущая << 1 .. 35 36 37 38 39 40 < 41 > 42 43 44 45 46 47 .. 105 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100