Программирование >>  Дополнительные возможности наследования 

1 ... 88 89 90 [ 91 ] 92 93 94 ... 265


Рекомендуется

Перегружайте операторы, если код программы после этого станет четче и понятнее.

Возвращайте объекты класса из перегруженных операторов.

Не рекомендуется

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

Четвертая, и последняя, функция, предоставляемая компилятором для работы с объектами, если, конечно, вы не задали никаких дополнительных функций, это функция оператора присваивания (operator=()). Этот оператор используется всякий раз, когда нужно присвоить объекту новое значение, например:

CAT cat0ne(5,7); CAT catTwo(3,4);

... другие строки программы catTwo = catOne

В данном примере создан объект catOne, переменной которого itsAge присвоено значение 5, а переменной itsWeigth - 7. Затем создается объект catTwo со значениями переменных соответственно 3 и 4.

Через некоторое время объекту catTwo присваиваются значения объекта catOne. Что произойдет, если переменная itsAge является указателем, и что происходит со старыми значениями переменных объекта catTwo?

Работа с переменными-членами, которые хранят свои значения в области динамической памяти, рассматривалась ранее при обсуждении использования конструктора-копировщика (см. также рис. 10.1 и 10.2).

В С++ различают поверхностное и глубинное копирование данных. При поверхностном копировании происходит передача только адреса от одной переменной к другой, в результате чего оба объекта указывают на одни и те же ячейки памяти. В случае глубинного копирования действительно происходит копирование значений переменных из одной области памяти в другую. Различия между этими методами копирования показаны на рис. 10.3.

Все выщесказанное справедливо для присвоения данных. В случае использования оператора присваивания, процесс обмена данных протекает с некоторыми особенностями. Так, объект catTwo уже существует вместе со своими переменными, для каждой из которых вьщелены определенные ячейки памяти. В случае присвоения объекту новых значений предварительно необходимо освободить эти ячейки памяти. Что произойдет, если выполнить присвоение объекта catTwo самому себе:

catTwo = catTwo

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

Если не предусмофеть поддержку такой ситуации, то оператор присваивания сначала очистит ячейки памяти объекта catTwo, а затем попытается присвоить объекту catTwo свои собственные значения, которых уже не будет и в помине.

49758935



Чтобы предупредить подобную ситуацию, ваш оператор присваивания прехсде всего должен определить, не совпадают ли друг с другом объекты по обе стороны от оператора присваивания. Это можно осуществить с помощью указателя this, как показано в листинге 10.15.

Листинг ID.15. Онсратор присааивания

2 3 4 5 6 7

Листинг 10.15. Конструктор-копировщик

Sinclude <iostream.h>

class CAT {

public:

CAT(); конструктор no умолчанию

конструктор-копировщик и деструктор пропущены! int GetAgeO const { return *itsAge; } int GetWeightO const { return *itsWeight; } void SetAge(int age) { *itsAge = age; } CAT & operator=(const CAT &);

private:

int *itsAge; int ItsWeight;

CAT::CAT() {

itsAge = new int; itsWeight = new int; itsAge = 5; itsWeight = 9;

CAT & CAT::operator=(const CAT & rhs) {

if (this == &rhs)

return this; itsAge = rhs. GetAgeO; itsWeight = rhs. GetWeightO; return this;

int mainO {

CAT frisky;

cout friskys age: frisky.GetAgeO endl; cout Setting frisky to 6...\ n ;



45 46 47 48 49 50 51 52

frisky.SetAge(6); CAT whiskers;

cout whiskers age: whiskers.GetAge() endl; cout copying frisky to whiskers...\ n ; whiskers = frisky;

cout whiskers age: whiskers.GetAgeO endl; return 0;

* Л friskys age: 5

Setting frisky to 6. . . whiskers age: 5 copying frisky to whiskers... whiskers age: 6

ff В листинге 10.15 вновь используется класс CAT. Чтобы не повторяться, в

данном коде пропущены объявления конструктора-копировщика и деструктора. В строке 14 объявляется оператор присваивания, определение которого представлено в строках 30-37.

В строке 32 выполняется проверка того, не является ли объект, которому будет присвоено значение, тем же самым объектом класса CAT, чье значение будет присвоено. Чтобы проверить это, сравниваются адреса в указателях rhs и this.

Безусловно, оператор присваивания (=) может быть произвольно перегружен таким образом, чтобы отвечать представлениям программиста, что означает равенство объектов.

Что происходит при попытке присвоить значение переменой одного из базовых типов, таких как int или unsigned short, объекту класса, объявленного пользователем? В листинге 10.16 мы опять вернемся к классу Counter и попытаемся присвоить объекту этого класса значение переменной типа int.

предуореждение

Листинг 10.16 не компилируйте!

Аисшинг 10.16. Попытка просвопть пбъвкту КАасся Counter зпачвнов иврвмвннвО тона int

Листинг 10.16.

Эту программу не компилируйте!

ftinclude <iostream.h> class Counter

46857



1 ... 88 89 90 [ 91 ] 92 93 94 ... 265

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика