{ cout<<’\n’<<”x=”<<obj.GetX() <<” y=”<<obj.GetY(); }
T sum (T obj1, T obj2) // хотя закрытые данные функция -друг
{ obj1. x + =obj2. x; // имеет право обращаться к компонентам
obj1. y + =obj2. y;
return obj1; }
#include <iostream.h>
void main () {
T e1 (1, 10); // создаем объект
Print (e1); // первое копирование - приращение
T e2 = e1; // второе копирование
Print (e2); // третье копирование
T e3 = sum (e1, e2); // четвертые копирования
Print (e3); // пятое копирование
}
// выведется:
// x= 2 y = 11
x= 3 y = 12
x= 7 y = 25
1) При копировании e1 в локальную переменную obj в функции Print,
в данные объекта obj передадутся значения x и y объекта e1 с
инкрементом, которые и будут выведены функцией (x = 2 y = 11)
2) При копировании в e1 в e2, в объект e2 передадутся
инкрементированные значения x и y объекта e1 (2 и 11- значения
данных объекта e2).
3) Затем при вызове Print(e2), значения объекта e2 копируются в локальную
переменную obj в функции Print. В obj передадутся значения x и y из
e2 с инкрементом они и будут выведены (x= 3 y = 12).
4) Затем в локальные переменные obj1 obj2 функции sum копируются
данные объектов e1 e2 с инкрементом в obj1 -(2 11), в obj2 - (3 12).
Локальные объекты суммируются в функции. Результирующий объект
имеет значения данных (5 23).
Данные этого объекта копируются с инкрементом в данные объекта e3 в
выражении T e3 = sum (…); т.е. e3 получает данные (6 24).
5) При вызове Print(e3), значения объекта e3 копируются в локальную
переменную obj в функции Print. В obj передадутся значения x и y из
e3 с инкрементом они и будут выведены (x= 7 y = 25).
Как мы видели выше, копирование по умолчанию осуществляет правильное копирование и без определения конструктора копирования в классе. Свой конструктор копирования нужен не всегда.
Обязательное его определение в тех случаях, когда класс содержит поля, являющиеся указателями на динамические участки памяти.
#include <iostream.h>
#include <conio.h>
class My {
int* p;
public:
My (int a) // встроенный конструктор с параметром
{ p= new int; *p = a; }
My (const My & obj) // конструктор копирования с инкрементом
{ p = new int; *p = *obj.p+1; }
/* Для фиксации вызова конструктора копирование также проводится с
инкрементом.
Конструктор копирования, создавая копию объекта, сначала выделяет
память под данное- член нового объекта и затем присваивает ему
значение, взятое из объекта – аргумента. Правильное присваивание
(без инкремента): *p = *obj.p;
*/
int Get () { return * p } // возвращает значение по адресу указателя
~My () { delete (p); } // деструктор память, выделенную под данное
// объекта освобождает
};
void Print (My obj) // функция вывода на экран самой переменной
{ cout<< ‘\n’ << obj.Get ();}