Задачи 190-196. Перегрузка операторов

190. Включите в класс Fraction операторы деления, получения обратной дроби, сокращения дроби. Выберите для этих действий подходящие символы операторов.

191. Добавьте в класс Complex три статических члена для подсчета количества вызовов каждого из трех конструкторов класса. Напечатайте значения данных счетчиков при завершении программы.

192. Замените три конструктора класса Complex одним конструктором с аргументами, имеющими значения по умолчанию:

Complex(double x = 0, double y = 0); //Конструктор

Проверьте работу программы.

193. Обратите внимание, что в класс комплексных чисел входят три оператора умножения: Complex на Complex, Complex на double и
double на Complex и только один оператор деления – Complex на Complex. Объясните, почему не возникает ошибки в инструкции

p3 = -p / 3;

в которой Complex делится на int. Сократите число операторов умножения.

194. Напишите функцию для решения квадратного уравнения с комплексными коэффициентами.

195. Напишите функцию для решения полного кубического уравнения

Задачи 190-196. Перегрузка операторов - student2.ru

с комплексными коэффициентами. Подстановкой

Задачи 190-196. Перегрузка операторов - student2.ru ,

получается каноническое уравнение

Задачи 190-196. Перегрузка операторов - student2.ru ,

где

Задачи 190-196. Перегрузка операторов - student2.ru .

Каноническое уравнение решается по формулам Кардано

196. Напишите класс Integral, включающий указатель на функцию для вычисления некоторой математической функции и границы отрезка ее области определения. Предусмотрите в классе функцию-оператор для вычисления значения интеграла на заданном отрезке.

Глава 18. Конструктор копирования и оператор присваивания

Проблемы при копировании

Присваивание и копирование объектов уже рассматривалось в §15.7 на примере класса Date. Для простых классов, не содержащих указатели, проблем не возникает, достаточно встроенного почленного копирования одного объекта в другой объект. Посмотрим, что произойдет при выполнении копирования и инициализации для класса, включающего указатели на выделяемую в конструкторе класса память, на примере многоугольников из программы 48.

Приведем сокращенное объявление класса:

class Plgn // Класс многоугольников

{

int n; // Число вершин

float *x; float *y; // Указатели на массивы абсцисс и ординат

static int x0, y0; // Координаты центра

public:

Plgn(int n = 3); // Конструктор с аргументом по умолчанию

~Plgn() { delete [] x; delete [] y; } // Деструктор освобождает память

static void SetBegCoord(int xn, int yn) // Установка координат центра

{ x0 = xn; y0 = yn; }

};

# include <stdlib.h> // Доступ к random

Plgn::Plgn(int nn) // Конструктор

{…} // Здесь выделяется память под массивы абсцисс и ординат

Напишем функцию badcopy, которая создает и копирует многоугольники.

void badcopy()

{

Plgn P(5); // (1) Создание пятиугольника

Plgn T; // (2) Создание треугольника

Plgn Q = P; // (3) Создание копии Q пятиугольника P

T = P; // (4) Попытка превратить треугольник в пятиугольник

} // (5) Удаление Q, T, P

Рассмотрим манипуляции с памятью, которые выполняет badcopy, рис.43. На шаге (1) создается пятиугольник P со своей переменной n и своими указателями x, y, которые указывают на массивы памяти, выделенные в конструкторе. На шаге (2) создается треугольник T, имеющий свои n, x, y и свои массивы координат. На шаге (3) создается многоугольник Q, у которого n, x, y имеют те же значения, что и у многоугольника P. Указатели Q.x, Q.y указывают на ту же память, что и P.x, P.y. На шаге (4) за счет присваивания T.n, T.x, T.y получают такие же значения, как P.n, P.x, P.y. В результате возникли две проблемы.

Первая проблема состоит в том, что потеряна связь с памятью, выделенной треугольнику T. Память, выделяемая динамически оператором new, должна освобождаться явно оператором delete, в противном случае она все равно будет числится за программой, потерявшей с ней связь. Произойдет «утечка памяти».

 
  Задачи 190-196. Перегрузка операторов - student2.ru

Вторая проблема состоит в том, что теперь на одну и ту же область памяти ссылаются по три указателя. При завершении функции badcopy будут вызваны деструкторы объектов P, T, Q, которые три раза освободят одну и ту же память.

Рис.43. Работа с памятью функции badcopy

Можно попробовать выполнить следующую программу, использующую badcopy:

int Plgn::x0, Plgn::y0; // Определение статических членов класса

# include <conio.h>

void main()

{

Plgn::SetBegCoord(100, 100); // Установл. значен. статич. членов

badcopy();

}

Скорее всего ее выполнение приведет к системной ошибке.

Чтобы избежать указанных проблем, в классе, содержащем указатели, следует перегрузить оператор присваивания, в котором предусмотреть выделение памяти под объект-копию. Такие же действия нужно выполнить в конструкторе копирования, который используется при инициализации создаваемого объекта другим, ранее созданным объектом. Пример перегрузки оператора присваивания и создания конструктора копирования приведен в следующей программе.



Наши рекомендации