• Like
02 Copying Objects
Upcoming SlideShare
Loading in...5
×

02 Copying Objects

  • 365 views
Uploaded on

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
365
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
2
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Бублик Володимир Васильович Програмування - 2 Лекція 2. Об'єктне програмування. Копіювання об'єктів Лекції для студентів 2 курсу
  • 2. Повторення
    • Що має бути в класі
    • class T
    • {
    • private :
    • // Тут розміщують атрибути
    • public :
    • // Конструктори
    • T(T1,…,Tn);
    • // Деструктор
    • ~T(); // далі селектори, модифікатори, …
    • };
  • 3. Клас 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. Питання
    • Чи коректно наступне визначення? ― Ні. Чому?
    • class String
    • {
    • private :
    • size_t _len;
    • char * _allocator;
    • public :
    • String();
    • String( const char * ps=0 );
    • String( const char );
    • ~String();
    • };
  • 5. Конструктор копіювання
    • class T
    • {
    • T(T1,…,Tn);
    • ~T();
    • // конструктор копіювання
    • // створює новий об'єкт, ідентичний
    • // переданому параметром
    • T( const T&);
    • // Можливий варіант: T(T&);
    • // але не Т(Т)
    • };
  • 6. Використання
    • Конструктор копіювання викликається кожного разу, коли параметр або результат передаються значеннями
    • T1 f(T2 x)
    • {
    • T1 y;…
    • return y;
    • }
    • a=f(b); // T2 x(b); … ; a = T1(y);
  • 7. Інвентаризація об'єктів
    • class Point
    • {
    • static int _ freeID;
    • const int _pointID;
    • double _x;
    • double _y;
    • public:
    • Point ( double x=0, double y=0 );
    • Point ( const Point &);
    • ~Point() ;
    • };
  • 8. Конструктор Point
    • Point::Point ( double x, double y):
    • _x (x),
    • _y (y),
    • pointID (++ _ freeID)
    • {
    • cout<<pointID<<&quot;: created &quot;<<* this <<endl;
    • return ;
    • };
  • 9. Копіювальний конструктор Point
    • Point::Point ( const Point & u):
    • _x (u._x),
    • _y (u._y),
    • pointID(++_freeID)
    • {
    • cout<<pointID<<&quot;: copied &quot;<<* this <<endl;
    • return ;
    • };
  • 10. Деструктор Point
    • Point::~Point()
    • {
    • cout<<pointID<<&quot;: removed &quot;<<* this <<endl;
    • return ;
    • };
  • 11. Передача об'єктів параметрами
    • Значенням
    • 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<<'('<<u.x()<<','<<u.y()<<')';
    • return os;
    • }
  • 12. Протокол
    • 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
  • 13. Вправа до передачі об'єктів параметрами
    • Що зміниться в протоколі, якщо у виводі забрати сталу відсилку?
    • ostream& operator <<(ostream &os, Point u )
    • {
    • os<<'('<<u.x()<<','<<u.y()<<')';
    • return os;
    • }
  • 14. Без локальної змінної
    • 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() );
    • }
  • 15. Протокол 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
  • 16. Сталі відсилки
    • Point operator + ( const Point & u, const Point & v)
    • {
    • return Point ( u.x()+v.x(), u.y()+v.y() );
    • }
  • 17. Протокол 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
  • 18. Урок передачі параметрів
    • Передаючи параметр і одержуючи результат, усвідомлюйте, з чим маєте справу: з оригіналом чи копією
  • 19. Копіювання агрегатів
    • class WrappedVector
    • {
    • private:
    • static const int n;
    • double * v;
    • public :
    • WrappedVector();
    • WrappedVector(const WrappedVector&);
    • ~WrappedVector();
    • };
  • 20. Копіювальний конструктор вектора
    • WrappedVector::
    • WrappedVector ( const WrappedVector& vec):
    • _v ( new double [_n])
    • {
    • if (_v==0) ; //do smth
    • for ( int i=0; i<_n; i++)
    • _v[i] = vec._v[i];
    • return ;
    • }
  • 21. Копіювальний конструктор за замовчуванням
    • WrappedVector::
    • WrappedVector ( const WrappedVector& vec):
    • _v ( vec._v)
    • { } ;
    • // Чим закінчиться виконання програми ?
    • int main ()
    • {
    • WrappedVector u, v(u) ;
    • return 64; // катастрофою!!!
    • }
  • 22. Копіювання присвоєнням
    • class WrappedVector
    • {
    • private :
    • static const int n;
    • double * v;
    • public :
    • WrappedVector();
    • WrappedVector( const WrappedVector&);
    • ~WrappedVector();
    • WrappedVector& operator = ( const WrappedVector&);
    • };
  • 23. Реалізація копіювального присвоєння
    • WrappedVector& WrappedVector:: operator = ( const WrappedVector& vec)
    • {
    • // Нам поталанило: vec і this мають одну й ту ж довжину
    • for ( int i=0; i<n; i++)
    • v[i] = vec.v[i];
    • return * this ;
    • }
  • 24. Присвоєння за замовчуванням
    • WrappedVector& WrappedVector:: operator = ( const WrappedVector& vec)
    • {
    • v = vec;
    • return * this ;
    • }
    • // Чим закінчиться виконання програми ?
    • int main ()
    • {
    • WrappedVector u, v;
    • u=v;
    • return 64; // катастрофою!!!
    • }
  • 25. Вектори різної довжини
    • class DissimilarVector
    • {
    • private :
    • int _ n; //non static, non const( ? )
    • double * _ v;
    • public :
    • DissimilarVector( int );
    • DissimilarVector( const DissimilarVector&);
    • ~DissimilarVector();
    • DissimilarVector& operator=( const DissimilarVector&);
    • };
  • 26. Конструктор вектора
    • DissimilarVector::
    • DissimilarVector ( int len ) :
    • _ n ( len ),
    • _ v ( new double[n ])
    • {
    • if ( _ v==0) // throw exeption
    • for ( int i=0; i< _ n; i++)
    • _ v[i] = 0;
    • return ;
    • }
  • 27. Копіювальний конструктор
    • DissimilarVector::
    • DissimilarVector ( const DissimilarVector& vec):
    • _n ( vec ._n),
    • _v ( new double [ vec ._n])
    • {
    • if (_v==0) // throw exeption
    • for ( int i=0; i<_n; i++)
    • _v[i] = vec._v[i];
    • return ;
    • }
  • 28. Чому атрибут _ n не може бути сталим?
    • Спробуйте присвоєння за замовчуванням
    • Навіть копіювальне присвоєння, взагалі кажучи, не працюватиме
  • 29. Копіювальне присвоєння
    • DissimilarVector& DissimilarVector:: operator = ( const DissimilarVector& vec)
    • {
    • //1. Видалити старий об'єкт
    • if ( this ==&vec)
    • return *this;
    • delete [] _ v;
    • //2. Створити новий об'єкт
    • _ n = vec. _ n;
    • _ v = new double [ _ n];
    • //1. Скопіювати значення
    • for ( int i=0; i< _ n; i++)
    • _ v[i] = vec. _ v[i];
    • return * this ;
    • }
    _ n = vec. _ n
  • 30. Рядки з копіюванням
    • class String
    • {
    • private :
    • size_t _len;
    • char * _allocator;
    • public :
    • String();
    • String( const char *);
    • String( const char );
    • String ( const String & s);
    • ~String();
    • };
  • 31. Копіювальний конструктор рядка
    • String::String(String& s)
    • _len( s._len),
    • _allocator( new char [_len+1])
    • {
    • strcpy(_allocator, s._allocator);
    • return ;
    • };
  • 32. Редагування оригіналу (без const)
    • class String
    • {
    • private :
    • size_t _len;
    • char * _allocator;
    • int _amountOfCopies ;
    • public :
    • String();
    • String( const char *);
    • String( const char );
    • String (String & s);
    • ~String();
    • };
  • 33. Копіювання з редагуванням
    • String::String(String& s)
    • _amountOfCopies (0),
    • _len( s._len),
    • _allocator( new char [_len+1])
    • {
    • // Кількість копій, зроблених з оригіналу
    • // збільшується на одиницю
    • s._amountOfCopies++;
    • strcpy(_allocator, s._allocator);
    • return ;
    • };
  • 34. Мультиконструктор копіювання
    • class String
    • {
    • public :
    • String();
    • String( const char *);
    • String( const char );
    • String( const String & s, int multiplayer=1);
    • ~String();
    • };
  • 35. Реалізація мультиконструктора копіювання
    • String:: String( const String & s, int multiplayer):
    • _len (s._len*multiplayer),
    • _allocator ( new char [_len+1])
    • {
    • char * target = _allocator;
    • for ( int i=0; i<multiplayer; i++)
    • {
    • strcpy(target, s._allocator);
    • target+=s._len;
    • }
    • return ;
    • };
  • 36. Застосування копіювання
    • // Common constructor
    • String s(p);
    • // Copy version of multiplication constructor
    • String ss(s);
    • // Multiplication constructor
    • String s10(s,10);
  • 37. Проблема замовчуваного параметру
    • Що станеться, якщо замовчуваний параметр перенести до реалізації? ― Катастофа
    • class String
    • {
    • public :
    • String( const String & s, int multiplayer);
    • };
    • String:: String( const String & s, int multiplayer =1 ): …{…;}
    • Чому?
  • 38. Некоректне копіювання
    • // Common constructor
    • String s(p);
    • // Default copy constructor
    • String ss(s);
    • // Multiplication constructor
    • String s10(s,10);
  • 39. Сигнатури присвоєнь
    • Якій з сигнатур віддати перевагу?
    • void operator =( T&) ;
    • T operator =( T&) ;
    • T& operator =( T ) ;
    • T operator =( T ) ;
    • T& operator =( T & ) ;
  • 40. Сигнатури присвоєнь
    • Якій з сигнатур віддати перевагу?
    • void operator =( T&) ;
    • T operator =( T&) ;
    • T& operator =( T ) ;
    • T operator =( T ) ;
    • T& operator =( T & ) ;
    T& operator =( const T & ) ;
  • 41. Сигнатури присвоєнь
    • Якій з сигнатур віддати перевагу?
    • void operator =( T&) ; // Як бути з x=y=z;
    • T operator =( T&) ; // чим копіювати результат?
    • T& operator =( T ) ; // чим копіювати параметр?
    • T operator =( T ) ; // див 2 і 3 разом
    • T& operator =( T & ) ; // ОК!!!
  • 42. Що таке this?
    • class T
    • {
    • public :
    • T(T1,…,Tn);
    • ~T();
    • T( const T&);
    • T& operator = ( const T&);
    • };
    • this має тип T * const
  • 43. Чому * const ?
    • this не можна перемістити на інший об'єкт
    • this = anything; не коректно
  • 44. Повернення значення в присвоєнні
    • Point& Point:: operator =( const Point & u)
    • {
    • this ->_x = u._x;
    • * this ._y = u._y;
    • return * this ;
    • }
  • 45. Рядки з присвоєнням
    • class String
    • {
    • public :
    • String();
    • String( const char *);
    • String( const char );
    • String( const String & s, int multiplayer=1);
    • String& operator =( const String&);
    • ~String();
    • };
  • 46. Присвоєння рядків
    • 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 ;
    • }
  • 47. Висновки
    • Конструктор копіювання створює новий об'єкт
    • Присвоєння звичайно замінює існуючий об'єкт іншим об'єктом (навіть якщо не доводиться видаляти попередні значення)
    • Присвоєння не можна визначити поза класом
    • Присвоєння в класі T має тип T& (чому?)
    • Присвоєння повертає *this , конструктори не повертають нічого (чому?)