Об'єктне програмування. Копіювання об'єктів. (Частина 1. Лекція 2)

Содержание

Слайд 2

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Повторення Що має

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Повторення

Що має бути в

класі
class T
{
private:
// Тут розміщують атрибути
public:
// Конструктори
T(T1,…,Tn);
// Деструктор
~T(); // далі селектори, модифікатори, …
};
Слайд 3

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Приклад класу. String

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Приклад класу. String

class String

{
private:
size_t _len;
char* _allocator;
public:
String();
String(const char*);
String(const char);
~String();
size_t length() const {return _len;}
bool empty() const {return _len==0;}
void clear() {*this=String();}
};
Слайд 4

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Констуктори Для чого

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Констуктори

Для чого у класі

три різних конструктори?
class String {
private:
size_t _len;
char* _allocator;
public:
String();
String(const char*);
String(const char);
……………………………………………
};
Слайд 5

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Властивість інкапсуляції Відокремлення

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Властивість інкапсуляції

Відокремлення реалізації класу

від його визначення
String::String (const char c):
_allocator( new char [2]),
_len(1)
{
_allocator [0]=c;
_allocator [1]='\0';
return;
}
Слайд 6

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Питання Чому у

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Питання

Чому у визначенні класу

розміщені реалізації?
class String
{
private:
size_t _len;
char* _allocator;
public:…………………………………………..
size_t length() const {return _len;}
bool empty() const {return _len==0;}
void clear() {*this=String();}
};
Слайд 7

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Питання Чи коректний

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Питання

Чи коректний параметр замовчування?

― Ні. Чому?
class String
{
private:
size_t _len;
char* _allocator;
public:
String ();
String (const char* ps=0);
String (const char);
~String ();
};
Слайд 8

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Конструктор копіювання class

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

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

class T
{
T(T1,…,Tn);
~T();
// конструктор копіювання
// створює

новий об'єкт, ідентичний
// переданому параметром
T(const T&);
// Можливий варіант: T(T&);
// але не Т(Т)
};
Слайд 9

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Використання Конструктор копіювання

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Використання

Конструктор копіювання викликається кожного

разу, коли параметр або результат передаються значеннями
T1 f(T2 x)
{
T1 y;
// тіло f…
return y;
}
a=f(b); // T2 x(b); T1 y; тіло f… ; a = T1(y);
Слайд 10

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Облік об'єктів (Off

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Облік об'єктів (Off top)

"Тьоркін

на тім світі…“
Олександр Твардовський
– Як це так – без виробництва? –
Теркін знову пристає, –
І щоб тільки керівництво!..
– Ні, ще облік у нас є...
Переклад Марка Кайдаша
Слайд 11

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Інвентаризація об'єктів class

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Інвентаризація об'єктів

class Point
{
static int

_freeID;
const int _pointID;
double _x;
double _y;
public:
Point (double x=0, double y=0);
Point (const Point &);
~Point();
};
Слайд 12

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Конструктор Point Point::Point

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Конструктор Point

Point::Point (double x,

double y):
_x (x),
_y (y),
pointID (++_freeID)
{
#ifdef NDEBUG
cout<#endif
return;
};
// Де коректно розмістити замовчування параметру?
Слайд 13

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Копіювальний конструктор Point

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Копіювальний конструктор Point

Point::Point (const

Point & u):
_x (u._x),
_y (u._y),
pointID(++_freeID)
{
#ifdef NDEBUG
cout<#endif
return;
};
// Чи може копіювання мати замовчуваний параметр?
Слайд 14

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Замовчування у копіювальному

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Замовчування у копіювальному конструкторі

class

Foo;
int main() {
Foo f1(10); // Створення нового об'єкту
Foo f2(f1); // Копіювання існуючого об'єкту
Foo f3; // Це що? Наперед невідомо
}
Слайд 15

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Перший варіант class

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Перший варіант

class Foo {
private:
int

_k;
static int _freeid;
const int _id;
public:
Foo(int k=0):_k(k), _id(++_freeid){
cout<<"New Foo id="<<_id< Foo(const Foo& foo=0):_k(foo._k), _id(++_freeid){
cout<<"New copy Foo id="<<_id<}
warning C4520: 'Foo' : multiple default constructors specified
Чому все-таки це дозволено? Foo& foo=0 проігноровано
Слайд 16

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Другий варіант class

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Другий варіант

class Foo {
private:
int

_k;
static int _freeid;
const int _id;
static Foo _static_foo;
public:
Foo(int k=0):_k(k), _id(++_freeid){
cout<<"New Foo id="<<_id<<", _k="<<_k<Foo(const Foo& foo=_static_foo):_k(foo._k),_id(++_freeid){
cout<<"New copy Foo id="<<_id<<", _k="<<_k<};
Тепер ігнорується int k=0
Слайд 17

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Експеримент int Foo::_freeid

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Експеримент

int Foo::_freeid = 0;
Foo

Foo::_static_foo(100);
int main() {
cout<<"START"< Foo f1(10);
Foo f2; // Копія об'єкту _static_foo
}
Зверніть увагу на порядок виконання дій
New Foo id=1, _k=100
START
New Foo id=2, _k=10
New copy Foo id=3, _k=100
Слайд 18

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Інший експеримент int

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Інший експеримент

int Foo::_freeid =

0;
int main() {
cout<<"START"< Foo f1(10);
Foo f2; // Копія об'єкту _static_foo
}
Foo Foo::_static_foo(100);
// Щось зміниться, якщо визначення Foo::_static_foo
// перенести до іншого місця?
Слайд 19

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Деструктор Point Point::~Point()

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Деструктор Point

Point::~Point()
{
#ifdef NDEBUG
cout<

"<<*this<#endif
return;
};
Слайд 20

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Передача об'єктів параметрами

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Передача об'єктів параметрами

Значенням
Point operator+

(Point u, Point v)
{
Point res(u.x()+v.x(), u.y()+v.y());
return res;
}
Відсилками
ostream& operator<<(ostream &os, const Point& u)
{
os<<'('< return os;
}
Слайд 21

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Протокол int main()

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Протокол

int main()
{
Point a(1,2);
Point b(5);
a+b;
return

0;
}

1: created (1,2) //a
2: created (5,0) //b
3: copied (5,0) //v
4: copied (1,2) //u
5: created (6,2) //res
6: copied (6,2) //return
5: removed (6,2) //res
4: removed (1,2) //u
3: removed (5,0) //v
6: removed (6,2) //returned
2: removed (5,0) //b
1: removed (1,2) //a

Слайд 22

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Вправа до передачі

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Вправа до передачі об'єктів

параметрами

Що зміниться в протоколі, якщо у виводі забрати сталу відсилку?
ostream& operator<<(ostream &os, Point u)
{
os<<'('< return os;
}

Слайд 23

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Без локальної змінної

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Без локальної змінної

Point operator+

(Point u, Point v)
{
/* Замість
Point res(u.x()+v.x(), u.y()+v.y());
return res;
*/
return Point ( u.x()+v.x(), u.y()+v.y() );
}
Слайд 24

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Протокол 2 int

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Протокол 2

int main()
{
Point a(1,2);
Point

b(5);
a+b;
return 0;
}

1: created (1,2) //a
2: created (5,0) //b
3: copied (5,0) //v
4: copied (1,2) //u
5: created (6,2) //return
4: removed (1,2) //u
3: removed (5,0) //v
5: removed (6,2) //returned
2: removed (5,0) //b
1: removed (1,2) //a

Слайд 25

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Сталі відсилки Point

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Сталі відсилки

Point operator+ (const

Point & u, const Point & v)
{
return Point ( u.x()+v.x(), u.y()+v.y() );
}
Слайд 26

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Протокол 3 int

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Протокол 3

int main()
{
Point a(1,2);
Point

b(1);
a+b;
return 0;
}

1: created (1,2) //a
2: created (5,0) //b
3: created (6,2) //return
3: removed (6,2) //returned
2: removed (5,0) //b
1: removed (1,2) //a

Слайд 27

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Урок передачі параметрів

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Урок передачі параметрів

Передаючи параметр

і одержуючи результат, усвідомлюйте, з чим маєте справу: з оригіналом чи копією
Слайд 28

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Копіювання агрегатів class

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Копіювання агрегатів

class WrappedVector
{
private:
static const

size_t n;
double * v;
public:
WrappedVector();
WrappedVector(const WrappedVector&);
~WrappedVector();
};
Слайд 29

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Копіювальний конструктор вектора

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Копіювальний конструктор вектора

WrappedVector::
WrappedVector (const

WrappedVector& vec):
_v (new double[_n])
{
for (size_t i=0; i<_n; i++)
_v[i] = vec._v[i];
return;
}
// Як бути з нестачею пам'яті?
Слайд 30

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Копіювальний конструктор за

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Копіювальний конструктор за замовчуванням

WrappedVector::
WrappedVector

(const WrappedVector& vec):
_v (vec._v)
{ };
// Чим закінчиться виконання програми?
int main()
{
WrappedVector u, v(u);
return 64; // катастрофою!!!
}
Слайд 31

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Копіювання присвоєнням class

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Копіювання присвоєнням

class WrappedVector
{
private:
static const

size_t n;
double * v;
public:
WrappedVector();
WrappedVector(const WrappedVector&);
~WrappedVector();
WrappedVector& operator= (const WrappedVector&);
};
Слайд 32

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Реалізація копіювального присвоєння

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Реалізація копіювального присвоєння

WrappedVector& WrappedVector::operator= (const

WrappedVector& vec)
{
//Нам поталанило: vec і this мають одну й ту ж довжину
for (size_t i=0; i v[i] = vec.v[i];
return *this;
}
Слайд 33

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Присвоєння за замовчуванням

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Присвоєння за замовчуванням

WrappedVector& WrappedVector

:: operator= (const WrappedVector& vec)
{
v = vec;
return *this;
}
// Чим закінчиться виконання програми?
int main()
{
WrappedVector u, v;
u=v;
return 64; // знову катастрофою!!!
}
Слайд 34

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Вектори різної довжини

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Вектори різної довжини

class DissimilarVector
{
private:
size_t

_n; //non static, non const(?)
double * _v;
public:
DissimilarVector(int);
DissimilarVector(const DissimilarVector&);
~DissimilarVector();
DissimilarVector& operator=(const DissimilarVector&);
};
Слайд 35

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Конструктор вектора DissimilarVector::

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Конструктор вектора

DissimilarVector::
DissimilarVector (size_t len)

:
_n (len),
_v (new double[n])
{
for (size_t i=0; i<_n; i++)
_v[i] = 0;
return;
}
Слайд 36

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Копіювальний конструктор DissimilarVector::

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Копіювальний конструктор

DissimilarVector::
DissimilarVector (const DissimilarVector&

vec):
_n (vec._n),
_v (new double[vec._n])
{
for (size_t i=0; i<_n; i++)
_v[i] = vec._v[i];
return;
}
Слайд 37

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Чому атрибут _n

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Чому атрибут _n не

може бути сталим?

Спробуйте присвоєння за замовчуванням
Навіть копіювальне присвоєння, взагалі кажучи, не працюватиме

Слайд 38

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Копіювальне присвоєння DissimilarVector&

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Копіювальне присвоєння

DissimilarVector& DissimilarVector::operator= (const DissimilarVector&

vec)
{
//1. Видалити старий об'єкт
if (this==&vec)
return *this;
delete [] _v;
//2. Створити новий об'єкт
_n = vec._n;
_v = new double[_n];
//3. Скопіювати значення
for (size_t i=0; i<_n; i++)
_v[i] = vec._v[i];
return *this;
}

_n = vec._n

Слайд 39

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Рядки з копіюванням

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Рядки з копіюванням

class String
{
private:
size_t

_len;
char* _allocator;
public:
String();
String(const char*);
String(const char);
String (const String & s);
~String();
};
Слайд 40

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Копіювальний конструктор рядка

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Копіювальний конструктор рядка

String::String(String& s)
_len(

s._len),
_allocator( new char[_len+1])
{
strcpy(_allocator, s._allocator);
return;
};
Слайд 41

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Редагування оригіналу (без

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Редагування оригіналу (без const)

class

String
{
private:
size_t _len;
char* _allocator;
int _amountOfCopies;
public:
String();
String(const char*);
String(const char);
String (String & s);
~String();
};
Слайд 42

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Копіювання з редагуванням

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Копіювання з редагуванням

String::String(String& s)
_amountOfCopies

(0),
_len( s._len),
_allocator( new char[_len+1])
{
// Кількість копій, зроблених з оригіналу
// збільшується на одиницю
s._amountOfCopies++;
strcpy(_allocator, s._allocator);
return;
};
Слайд 43

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Мультиконструктор копіювання class

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Мультиконструктор копіювання

class String
{
public:
String();
String(const char*);
String(const

char);
String(const String & s, int multiplayer=1);
~String();
};
Слайд 44

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Реалізація мультиконструктора копіювання

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Реалізація мультиконструктора копіювання

String:: String(const

String & s, int multiplayer):
_len (s._len*multiplayer),
_allocator (new char [_len+1])
{
char * target = _allocator;
for (int i=0; i {
strcpy(target, s._allocator);
target+=s._len;
}
return;
};
Слайд 45

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Застосування копіювання //

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Застосування копіювання

// Common constructor
String

s(p);
// Copy version of multiplication constructor
String ss(s);
// Multiplication constructor
String s10(s,10);
Слайд 46

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Проблема замовчуваного параметру

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Проблема замовчуваного параметру

Що станеться,

якщо замовчуваний параметр перенести до реалізації? ― Катастофа
class String
{
public:
String(const String & s, int multiplayer);
};
String:: String(const String & s, int multiplayer=1):…{…;}
Чому?
Слайд 47

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Некоректне копіювання #include

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Некоректне копіювання

#include “String.h”
// Common

constructor
String s(p);
// Default copy constructor
String ss(s);
// Multiplication constructor
String s10(s,10);
Слайд 48

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Сигнатури присвоєнь Якій

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Сигнатури присвоєнь

Якій з сигнатур

віддати перевагу?
void operator=( T&);
T operator=( T&);
T& operator=( T );
T operator=( T );
T& operator=( T&);
Слайд 49

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Сигнатури присвоєнь Якій

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Сигнатури присвоєнь

Якій з сигнатур

віддати перевагу?
void operator=( T&); // Як бути з x=y=z;
T operator=( T&); // чим копіювати результат?
T& operator=( T ); // чим копіювати параметр?
T operator=( T ); // див 2 і 3 разом
T& operator=( T&); // ОК!!!
Слайд 50

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Сигнатури присвоєнь Якій

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Сигнатури присвоєнь

Якій з сигнатур

віддати перевагу?
void operator=( T&);
T operator=( T&);
T& operator=( T );
T operator=( T );
T& operator=( T&);

T& operator=(const T&);

Слайд 51

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Що таке this?

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Що таке this?

class T
{
public:
T(T1,…,Tn);
~T();
T(const

T&);
T& operator= (const T&);
};
this має тип T * const
Слайд 52

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Чому * const?

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Чому * const?

this

не можна перемістити на інший об'єкт
this = anything; не коректно
Слайд 53

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Повернення значення в

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Повернення значення в присвоєнні
Point&

Point::operator=(const Point & u)
{
this ->_x = u._x;
*this._y = u._y;
return *this;
}
Слайд 54

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Рядки з присвоєнням

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Рядки з присвоєнням

class String
{
public:
String();
String(const

char*);
String(const char);
String(const String & s, int multiplayer=1);
String& operator=(const String&);
~String();
};
Слайд 55

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів Присвоєння рядків String&

© Бублик В.В. ООП-1. Об'єктне програмування. Копіювання об'єктів

Присвоєння рядків

String& String::operator=(const String&

s)
{
if (this==&s)
return *this;
delete [] _allocator;
_len = s._len;
_allocator = new char[_len+1];
strcpy(_allocator, s._allocator);
return *this;
}