Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Книга C++.doc
Скачиваний:
24
Добавлен:
10.11.2019
Размер:
2.48 Mб
Скачать

Домашнее задание

Задания первого уровня:

  1. Цифровой счетчик, это переменная с ограниченным диапазоном. Значение которой сбрасывается, когда ее целочисленное значение достигает определенного максимума (например, k принимает значения в диапазоне от 0..100). В качестве примера такого счетчика можно привести цифровые часы, счетчик километража. Опишите класс такого счетчика. Обеспечьте возможность установления максимального и минимального значений, увелечения счетчика на 1, возвращения текущего значения.

  2. Определите класс дробей - рациональных чисел, являющихся отношением двух чисел (а/b). Напишите методы для сложения, вычитания, умножения и деления дробей.

Задания второго уровня:

  1. К заданию первого уровня: "Определите класс дробей - рациональных чисел, являющихся отношением двух чисел (а/b). Напишите методы для сложения, вычитания, умножения и деления дробей.", - добавьте возможность приведения дроби к наименьшему знаменателю.

Конструктор копирования

Ну что ж, приступим! Сконцетрируйтесь, закройте глаза. Подумайте о чем-то хорошем. Я надеюсь, Вы подумали о С++. Отдохнули?

Продолжаем наше погружение в прекрасный мир совершенного языка. По крайней мере, некоторые так думают. По умолчанию, при инициализации одного объекта другим, С++ выполняет побитовое копирование (почленное копирование). Сильно сказано. Это означает, что один объект становится точной копией другого. Продемонстрируем всё вышесказанное на примере:

#include<iostream.h>

class A{

int a;

public:

void Set(int f){

a=f;

}

};

void main(){

A ist;

ist.Set(4);

A cpy=ist;//После выполнения этой строки cpy будет копией ist

}

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

Пример

Пусть у нас есть 2 обьекта G и J класса MyClass, выделяющего память при создании обьекта.Предположим, что обьект G уже существует. Это означает что обьект G уже выделил память. Далее предположим, что G использовался для инициализации обьекта J, как показано ниже:

MyClass J=G;

Если в данном случае используется побитовое копирование( почленное копирование). То J станет копией G. Это значит, что J будет использовать тот же участок выделенной памяти, что и G,вместо того, чтобы выделить свой. Это чрезвычайно плохо. Если например в классе MyClass есть деструктор, освобождающий память, то тогда одна и та же память будет очищена дважды при уничтожении G и J.

#include<iostream.h>

// Реализация описанного выше

class MyClass{

public:

int *x;

MyClass(){

x=new int;

}

~MyClass(){

delete x;

}

};

void main(){

// при создании обьекта G выделяется память в теле конструкторе

MyClass G;

// Вот-то и возникает проблема снова создаётся обьект,

// а память в конструкторе не выделяется.В итоге указатель

// J.x указывает в ту же область память ,что и G.x

MyClass J=G;

// при выходе из функции main 2 раза вызывается деструктор,

// который очищает память отведённую при создании обьекта

// то есть выполняется delete x для J и delete x для G

// а так как J.x=G.x то отсюда следует вывод, что 2 раза

// очищается одна и та же область памяти. Это повлечет за

// собой ошибку на этапе выполнения программы

}

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

#include<iostream.h>

class MyClass{

public:

int *x;

MyClass(){

x=new int;

}

~MyClass(){

delete x;

}

};

void f(MyClass d){

}

void main(){

// при создании обьекта G выделяется память в теле конструкторе

MyClass G;

// При передаче в функцию обьекта G по значению будет создана

// дополнительная копия обьекта.Это будет проделано с помощью

// побитового копирования (т.е. как обьяснялось выше память не будет

// выделена)

f(G);

}

Опять же возникнет ошибка на этапе выполнения программы !!!

Второй появляется , когда временный обьект создается

функцией возвращающей обьект в качестве своего значения.

Пример :

#include<iostream.h>

class MyClass{

public:

int *x;

MyClass(){

x=new int;

cout<<"It's me";

}

~MyClass(){

delete x;

}

};

MyClass f(){

MyClass s;

// та же ошибка!!! При возврате значения создаётся побитовая копия

// под которую не выделяется память

return s;

}

void main(){

f();

}

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