Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Цуканов Б.И. "Время в психике человека" (Медицина)

Суворов С. "Танк Т-64. Первенец танков 2-го поколения " (Военная промышленность)

Нестеров В.А. "Основы проэктирования ракет класса воздух- воздух и авиационных катапульных установок для них" (Военная промышленность)

Фогль Б. "101 вопрос, который задала бы ваша кошка своему ветеринару если бы умела говорить" (Ветеринария)

Яблоков Н.П. "Криминалистика" (Юриспруденция)
Реклама

Самоучитель С++ - Шилдт Г.

Шилдт Г. Самоучитель С++ — Спб.: БВХ-Петербург, 2003. — 688 c.
ISBN 5-7791-0086-1
Скачать (прямая ссылка): samouchitelc2003.djvu
Предыдущая << 1 .. 24 25 26 27 28 29 < 30 > 31 32 33 34 35 36 .. 206 >> Следующая

2. Следует быть внимательными при возвращении объектов из функций, если эти объекты содержат деструктор, поскольку возвращаемый объект выходит из области видимости, как только функция возвращает его значение. Например, если функция возвращает объект, имеющий деструктор, который освобождает динамически выделенную память, то эта память будет освобождена независимо от того, использует ли ее объект, которому присваивается возвращаемое значение, или нет. Например, рассмотрим неправильную версию предыдущей программы:
// При возвращении объекта генерируется ошибка #include <iostream>
#include < с string > ttinclude <cstdlib> using namespace std;
class samp { char *s; public:
samp() { s = ' \0 '; }
~samp() { if (s) free(s);
cout « "Освобождение памяти по адресу s\n";) void show(} { cout « s << "\n"; } void set{char *str);
i-;
// Загружает строку void samp: : set(char *str)
(
s = (char *} malloc (strlen(str)+1) ;
if ( ! s) {
cout « "Ошибка выделения памяти\п''; exit(1);
}
strcpy(s,str) ;
}
// Возвращает объект типа samp samp input {)
{
char s[80] ;
samp str;
cout << "Введите строку: 11;
сіп» s ;
36 Самоучитель C++
str.set(sj; return str;
int tnainO
{
samp ob;
/ / возвращаемое значение присваивается объекту ob ob = input {); // Это ведет к ошибке ob«show() ;
return 0;
Здесь показан результат работы программы:
Введите строку: Привет
Освобождение памяти по адресу s
Освобождение памяти по адресу s
Привет
Освобождение памяти по адресу s Null pointer assignment
Обратите внимание, что деструктор класса samp вызывается трижды. Первый раз, когда локальный объект str выходит из области видимости при возвращении функцией input() своего значения. Второй раз ~samp() вызывается
тогда, когда удаляется временный объект, возвращаемый функцией input().
Запомните, когда объект возвращается функцией, автоматически генерируется невидимый (для вас) временный объект, который и хранит возвращаемое значение. В этом случае временный объект — это просто копия объекта str, являющегося возвращаемым значением функции. Следовательно, после того как функция возвратила свое значение, выполняется деструктор временного объекта. И наконец, при завершении программы вызывается деструктор объекта ob в функции main().
Проблема в этой ситуации в том, что при первом выполнении деструктора память, выделенная для хранения вводимой с помощью функции input() строки, освобождается. Таким образом, при двух других вызовах деструктора класса samp не только делается попытка освободить уже освобожденный блок динамической памяти, но в процессе работы происходит разрушение самой системы динамического распределения памяти и, как доказательство этому, появляется сообщение "Null pointer assignment". (В зависимости от вашего компилятора, модели используемой памяти и тому подобного при попытке выполнить программу это сообщение может и не появиться.)
Ключевым моментом в понимании проблемы, описанной в этом примере, является то, что при возвращении функцией объекта для временного объекта, который и является возвращаемым значением функции, вызывается дест-
Глава 3. Подробное изучение классов_________________________________________97
руктор. (Как вы узнаете в главе 5, для решения проблемы в такой ситуации можно воспользоваться конструктором копий.)
Для внимательного изучения вопроса, когда при возвращении функцией объекта для него вызываются конструктор и деструктор, создайте класс who. Конструктор who должен иметь один символьный аргумент, который будет использоваться для идентификации объекта. При создании объекта конструктор должен выводить на экран сообщение:
Создание объекта who #х
где х — идентифицирующий символ, свой для каждого объекта. При удалении объекта на экран должно выводиться примерно такое сообщение:
Удаление объекта who #х
где х — снова идентифицирующий символ. Наконец, создайте функцию make_who(), которая возвращает объект who. Присвойте каждому объекту уникальное имя. Проанализируйте выводимый на экран результат работы программы.
2. Продумайте ситуацию, в которой, как и при неправильном освобождении динамической памяти, возвращать объект из функции было бы также ошибочно.
3.4. Дружес т венные функции: обзор
Возможны ситуации, когда для получения доступа к закрытым членам класса вам понадобится функция, не являющаяся членом этого класса. Для достижения этой цели в C++ поддерживаются дружественные функции (friend functions). Дружественные функции не являются членами класса, но тем не менее имеют доступ к его закрытым элементам.
В пользу существования дружественных функций имеются два довода, связанные с перегрузкой операторов и созданием специальных функций ввода/вывода. Об этом использовании дружественных функций вы узнаете несколько позднее. Сейчас познакомимся с третьим доводом в пользу существования таких функций. Вам наверняка когда-нибудь понадобится функция, которая имела бы доступ к закрытым членам двух или более разных классов. Рассмотрим, как создать такую функцию.
Предыдущая << 1 .. 24 25 26 27 28 29 < 30 > 31 32 33 34 35 36 .. 206 >> Следующая