|
Программирование >> Расширенная версия языка c++
36 Самоучитель C++, str. set (s) ; .. : -i. / return str; i . К -- int mainO samp ob; / / возвращаемое значение присваивается объекту ob ob = ii-LuL О; Это ведет к ошибке оЬ.show(); return 0; 4:.f;F Здесь показан результат работы программы: Введите строку: Привет Освобождение памяти по адресу s Освобождение памяти по адресу s Привет Освобождение памяти по адресу s Null pointer assignment , . Обратите внимание, что деструктор класса samp вызывается трижды. Первый когда локальный объект выходит из области видимости при возвращении функцией input() своего значения. Второй раз ~samp() вызывается тогда, когда удаляется временный объект, возвращаемый функцией input(). Запомните, когда объект возвращается функцией, автоматически генерируется невидимый (для вас) временный объект, который и хранит возвращаемое значение. В этом случае временный объект - это просто копия объекта str, являющегося возвращаемым значением функции. Следовательно, после того как функция возвратила свое значение, выполняется деструктор временного объекта. И наконец, при завершении программы вызывается деструктор объекта ob в функции mainO- Проблема в этой ситуации в том, что при первом выполнении деструктора память, выделенная для хранения вводимой с помощью функции input() строки, освобождается. Таким образом, при двух других вызовах деструктора класса samp не только делается попытка освободить уже освобожденный блок динамической памяти, но в процессе работы происходит разрушение самой системы динамического распределения памяти и, как доказательство этому, появляется сообщение Null pointer assignment . (В зависимости от вашего компилятора, модели используемой памяти и тому подобного при попытке выполнить программу это сообщение может и не появиться.) Ключевым моментом в понимании описанной в этом примере, является то, что при возвращении функцией объекта для временного объекта, который и является возвращаемым значением функции, вызывается дест- руктор. (Как вы узнаете в главе 5, для решения проблемы в такой ситуации можно воспользоваться конструктором копий.) 1. Для внимательного изучение отросп когда при возвращении функцией объекта для него вызываются конструктор и структр. создайте класс who. Конструктор who должен иметь один символьный аргумент, который будет использоваться для идентификации объекта. При создании объекта конструктор должен выводить на экран сообщение: Создание объекта who #х ! r.i i где х - идентифицирующий символ, свой для каждого объекта. При удалении объекта на экран должно выводиться примерно такое сообщение: Удаление объекта who ttx где х снова идентифицирующий символ. Наконец, создайте функцию make who(), которая возвращает объект who. Присвойте каждому объекту уникальное имя. Проанализируйте выводимый на экран результат работы программы. 2. Продумайте ситуацию, в которой, как и при освобождении динамической памяти, возвращать объект из функции было бы также ошибочно. 3.4. Дружественные функции: обзор Возможны ситуации, когда для получения доступа к закрытым членам класса вам понадобится функция, не являющаяся членом этого класса. Для достижения этой цели в C++ поддерживаются дружественные функции (friend functions). Дружественные функции не являются членами класса, но тем не менее имеют доступ к его закрытым элементам. В пользу существования дружественных функций имеются два довода, связанные с перегрузкой операторов и созданием специальных функций ввода/вывода. Об этом использовании дружественных функций вы узнаете несколько позднее. Сейчас познакомимся с третьим доводом в пользу существования таких функций. Вам наверняка понадобится функция, которая имела бы доступ к закрытым членам двух или более разных как создать такую функцию. Дружественная функция задается так как обычная, не являющаяся членом класса, функция. Однако в объявление класса, для которого функция будет дружественной, необходимо включить ее прототип, перед которым ставится ключевое слово friend. Чтобы понять, как работает дружественная функция, рассмотрим следующую короткую программу: gg Самоучитель C++ II Пример использования дружественной функции tinclude <iostrearn> . . , . - usin space std; class myclass ( int n, d; public: гаусТр.яя Ont- i, int j) { n = i; d - j; } объявление дружественной функции для класса myclass friend int igfactor (myclass ob) ; ... Здесь представлено определение дружественной функции. Она возвращает истину, если n делится без остатка на d. Отметьте, что кочевое слово friend в оеделении функции LOf (; не используется. int isfactor (myclass ob) , . if(!(ob.n % ob.d)) return 1; ; else return 0; myclass if (isfactor(obl) cou << 10 без остатка делится на 2\n ; else cou 10 без остатка не делится на 2\п ; f if (isfactor(оЬ2) cou 13 без остатка делится на 3\п ; else cou 13 бе остатка не делится на 3\п ; return 0; В этом примере в объявлении класса myclass объявляются конструктор и дружественная функция isfactor(). Поскольку функция isfactor() дружественна для класса myclass, то функция isfactorQ имеет доступ к его закрытой части. Поэтому внутри функции isfactor() можно непосредственно ссылаться на объекгы оЬ.п и ob.d. Важно понимать, что дружественная функция не является членом класса, для которого она дружественна. Поэтому невозможно вызвать дружественную функцию, используя имя объекта и оператор доступа к члену класса (точку или стрелку). Например, по отношению к предыдущему примеру эта инструкция неправильна: оЫ. is factor О ; неправильно ctor () - это не функция-член
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |