Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа № 6Ссылка, перегрузка.doc
Скачиваний:
5
Добавлен:
13.09.2019
Размер:
103.94 Кб
Скачать

Конструктор копий

Вызов конструктора копий происходит при создании копии объекта, когда его передают функции по значению, а также при создании объекта из другого, уже существующего. Компилятор предоставляет стандартный конструктор копий, но для достаточно сложных объектов он не всегда ведет себя адекватно. Стандартный конструктор копий (поставляемый компилятором по умолчанию) просто копирует каждую переменную-член переданного ему объекта в переменные-члены нового объекта. Такое копирование называется поверхностным (shallow сору). Хоть оно и подхо­дит для большинства случаев, могут возникнуть серьезные проблемы, если переменные- члены являются указателями на объекты в динамической памяти.

В результате поверхностного копирования создаются точные копии значений всех переменных-членов одного объекта в другом. Указатели в обоих объектах будут ука­зывать на одну и ту же область памяти. Глубокое копирование переносит значения, на­ходящиеся в динамической памяти, во вновь созданные участки.

Задания 5. Создание конструктора копий с глубоким копированием

#include <vcl.h>

# include <iostream.h>

#include <conio.h>

using namespace std;

class Cat

{ private:

int *itsAge;

int *itsWeight;

public:

Cat (); // конструктор по умолчанию

Cat (const Cat &); // конструктор копий.

~Cat();

int GetAge() const {return *itsAge;}

int GetWeight() const {return *itsWeight;}

int SetAge(int age) {*itsAge = age;}

};

Cat::Cat()

{

itsAge=new int;

itsWeight=new int;

*itsAge=5;

*itsWeight=9;

}

Cat::Cat (const Cat& rhs)

{

itsAge=new int;

itsWeight=new int;

*itsAge=rhs.GetAge(); // Openning access

*itsWeight=*(rhs.itsWeight); // Closeing access

}

Cat::~Cat()

{

delete itsAge;

itsAge=0;

delete itsWeight;

itsWeight=0;

}

int main(int argc, char* argv[])

{

Cat frisky;

cout << "frisky's age: " << frisky.GetAge() << endl ;

cout << "Setting frisky to 6 ... \n";

frisky.SetAge(6);

cout << "Create object(cat) boots from frisky \n";

Cat boots(frisky);

cout << "frisky's age: " << frisky.GetAge() << endl ;

cout << "boots's age: " << boots.GetAge() << endl ;

cout << "Setting frisky to 7 ... \n";

frisky.SetAge(7);

cout << "frisky's age: " << frisky.GetAge() << endl ;

cout << "boots's age: " << boots.GetAge() << endl ;

getch();

return 0;

}

Объявленые две переменные-члена в создаваемом классе, представляют собой указатели на целочисленные значения. Обычно так не поступают, хранить в переменных-членах класса указатели на тип int абсолютно бессмысленно, здесь это сделано исключительно для примера манипулирования переменными-членами в динамической памяти.

Стандартный конструктор выделяет в динамической памяти об­ласть для двух переменных типа int и инициализирует их.

В конструкторе копий обратите внимание на параметр rhs. В качестве параметра конструктора копий принято использовать объект rhs, название ко­торого является сокращением от right-hand side (стоящий справа).

Конструктор копий работает следующим образом: выделяются области в ди­намической памяти, новым областям присваиваются значения существующего объекта класса САТ.

Параметр rhs, передаваемый в конструктор копий в качестве постоянной ссылки, соответствует объекту классу САТ. Являясь объектом класса САТ, rhs содержит все пере­менные-члены, присущие объекту класса САТ.

Каждый объект класса САТ может получать доступ к закрытым переменным-членам лю­бого другого объекта класса САТ, но обычно для этого принято создавать открытые методы доступа. Функция-член rhs.GetAge(), например, возвращает значение переменной- члена itsAge объекта rhs.

Когда объекты класса САТ выйдут из области действия, автоматически будут вызва­ны их деструкторы. Для обоих указателей, itsAge и itsWeight, выполняется оператор delete, освобождая выде­ленную для них память. Кроме того, в целях безопасности обоим указателям при­своено значение NULL.