с = b = a; // демонстрация множественного присваивания

 с.show();

 b.show();

 ++c; // префиксная версия инкремента

 c.show();

 с++; // постфиксная версия инкремента

 с. show();

 а = ++с; // Объект а получает значение объекта с после инкрементирования.

 a.show(); // В этом случае объекты а и с

 с.show(); // имеют одинаковые значения координат.

 а = C++; // Объект а получает значение объекта с до инкрементирования.

 a.show(); // В этом случае объекты а и с

 с.show(); // имеют различные значения координат.

 return 0;

}

Узелок на память.Для реализации перегрузки операторов следует использовать функции-члены. Функции-"друзья" используются в C++ в основном для обработки специальных ситуаций.

Перегрузка операторов отношения и логических операторов

Операторы отношений (например, "==" или "<") и логические операторы (например, "&&" или "||") также можно перегружать, причем делать это совсем нетрудно. Как правило, перегруженная операторная функция отношения возвращает объект класса, для которого она перегружается. А перегруженный оператор отношения или логический оператор возвращает одно из двух возможных значений: true или false. Это соответствует обычному применению этих операторов и позволяет использовать их в условных выражениях.

Рассмотрим пример перегрузки оператора "==" для уже знакомого нам класса three_d.

// Перегрузка оператора "=="

bool three_d::operator==(three_d op2)

{

 if((x == op2.x) && (y == op2.y) && (z == op2.z)) return true;

 else return false;

}

Если считать, что операторная функция operator==() уже реализована, следующий фрагмент кода совершенно корректен.

three_d а, b;

 // ...

if(а == b) cout << "а равно b\n";

else cout << "а не равно b\n";

Поскольку операторная функция operator==() возвращает результат типа bool, ее можно использовать для управления инструкцией if. В качестве упражнения попробуйте реализовать и другие операторы отношений и логические операторы для класса three_d.

Подробнее об операторе присваивания

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

Подобная проблема может возникать и при присваивании одного объекта другому. По умолчанию объект, находящийся с левой стороны от оператора присваивания, получает побитовую копию объекта, находящегося справа. К печальным последствиям это может привести в случаях, когда при создании объект выделяет некоторый ресурс (например, память), а затем изменяет его или освобождает. Если после выполнения операции присваивания объект изменяет или освобождает этот ресурс, второй объект также изменяется, поскольку он все еще использует его. Решение этой проблемы состоит в перегрузке оператора присваивания.

Чтобы до конца понять суть описанной проблемы, рассмотрим следующую (некорректную) программу.

// Ошибка, генерируемая при возврате объекта из функции.

#include

#include

#include

using namespace std;

class sample {

  char *s;

 public:

  sample() { s = 0; }

  sample(const sample &ob); // конструктор копии

  ~sample() {

   if(s) delete [] s;

   cout << "Освобождение s-памяти.\n";

  }

  void show() { cout << s << "\n"; }

  void set(char *str);

};

// Конструктор копии.

sample::sample(const sample &ob)

{

 s = new char[strlen(ob.s) +1];

 strcpy(s, ob.s);

}

// Загрузка строки.

void sample::set(char *str)

{

 s = new char[strlen(str) +1];

 strcpy(s, str);

}

Перейти на страницу:

Все книги серии Изучайте C++ с профессионалами

Похожие книги